1、printf(n);为了保证唯一地构造出所希望的二叉树,在键入这棵树的先序序列时,需要在所有空二叉树的位置上填补一个特殊的字符,比如, 。在算法中,需要对每个输入的字符进行判断,如果对应的字符是,则在相应的位置上构造一棵空二叉树;否则,创建一个新结点。整个算法结构以先序遍历递归算法为基础,二叉树中结点之间的指针连接是通过指针参数在递归调用返回时完成。int createbitree(bitree &T,int &sum)char ch;scanf(%c,&ch);if(ch=)T=NULL;elseif(!(T=(bitree)malloc(sizeof(binode)return 0;T-d
2、ata=ch;sum+;createbitree(T-lchild,sum);rchild,sum);return 1;具体实现过程为:#includemalloc.htypedef struct binodechar data;struct binode *lchild,*rchild;binode,*bitree;/定义树结点结构typedef struct queuenodebitree ch;struct queuenode *next;queuenode,*queueptr;/定义队列结点结构typedef structqueueptr front;queueptr rear;lin
3、kqueue;/定义队列指针/建树/初始化一个带头结点的队列void initqueue(linkqueue &q)q.front=q.rear=(queueptr)malloc(sizeof(queuenode);q.front-next=NULL;/入队列void enqueue(linkqueue &q,bitree p)queueptr s;int first=1;s=(queueptr)malloc(sizeof(queuenode);s-ch=p;q.rear-next=s;q.rear=s;/出队列void dequeue(linkqueue &q,bitree &p)s=q.f
4、ront-next;p=s-ch;data=p-data;next=s-if(q.rear=s)q.rear=q.front;free(s);%c ,data);/判断队列是否为空int queueempty(linkqueue q)if(q.front-next=NULL)/按层次遍历树中结点/主函数void main()int n=0;bitree bt;createbitree(bt,n);该二叉树共有%d个结点.n,n);按层次遍历树中结点其输出顺序为: ntraverse(bt);通过上机实践,帮助学生进一步掌握指针变量和动态变量的含义,掌握二叉树的结构特性,以及各种存储结构的特点及
5、适用范围,掌握用指针类型描述、访问和处理二叉树的运算。【实验内容】实验题目一:层序遍历二叉树【实验步骤】1 已知二叉树以二叉链表作为存储结构,写一个算法按层序遍历它,通过程序在终端屏幕上打印出它的层序序列。2 先建立二叉树的二叉链表存储结构,再遍历它。3 利用队列完成算法。编程实现以二叉链表存储的二叉树的中序遍历的非递归算法。编程实现二叉树的中序线索链表的生成(线索化)及其遍历的算法。实验题目二:交换二叉树的所有结点的左右子树1 已知二叉树以二叉链表作为存储结构,写一个算法交换该二叉树的所有结点的左右子树。2 先建立二叉树的二叉链表存储结构,再完成算法,注意结果的输出形式!3 利用栈。可设二叉
6、树的根指针为t,且以二叉链表表示,可利用一个指针栈来实现,且设栈单元包括数据域和指针域,当树非空时,将当前的树根结点进栈,同时将当前栈顶元素出栈当作根结点,然后依据当前的根结点是否具有孩子结点来判定是否将其左右指针交换;再将交换后的左指针或右指针入栈,如此反复,直到栈空。【程序说明】该程序集成了如下功能:(1) 二叉树的建立(2) 递归和非递归先序,中序和后序遍历二叉树(3) 按层次遍历二叉树(4) 交换二叉树的左右子树(5) 输出叶子结点(6) 递归和非递归计算叶子结点的数目#include conio.hmath.htypedef struct Binnode char data; str
7、uct Binnode *lchild; struct Binnode *rchild; Binnode; /*按照前序遍历建立二叉树*/void Creat_Bintree(Binnode *t) char ch; scanf(n%c if(ch=0) *t=NULL; else *t=(Binnode*)malloc(sizeof(Binnode); if(!*t)exit(OVERFLOW); (*t)- printf(%c: left,ch); Creat_Bintree(&(*t)- rightCreat_Bintree(& /*按照前序递归遍历二叉树*/void Preorder1
8、(Binnode *t) if(t!,t-data); Preorder1(t-/*按照中序递归遍历二叉树*/void Inorder1(Binnode *t) /* printf(n输出中序递归遍历序列:*/ Inorder1(t- /* 按照后序递归遍历二叉树*/void Posorder1(Binnode *t)n输出后序递归遍历序列: Posorder1(t-/*按照前序非递归遍历二叉树*/void preorder2(Binnode *root)/*先序非递归遍历二叉树*/ Binnode *p,*stack100; int top ; p=root; if(root! top=1;
9、 stacktop=p; while(top0) p=stacktop ;/*将右小孩放入栈*/ top-;,p- if(p- top+; stacktop=p-rchild;lchild;/*按照中序非递归遍历二叉树*/void Inorder2(Binnode *root)/*中序非递归遍历二叉树*/ int top=0;do while(p! top+; p=p- if(top p=stacktop;/*p所指的节点为无左子树或其左子树已经遍历过*/while(p!=NULL|top!=0);/*按照后序非递归遍历二叉树*/void Posorder2(Binnode *t) Binno
10、de *s100; int top=-1; int flag100; while(t!=-1) while(t) flagtop=0; stop=t; t=t-=0&flagtop=1) t=stop;=0) flagtop=1; t=NULL;/*按照层次遍历二叉树*/int front=0,rear=1;void Levelorder(Binnode *t) Binnode *q100; q0=t; /* int front=0,rear=1; while(front qrear+=qfront- front+;/*递归法将二叉树的左右子树互换*/void Exchange1(Binnod
11、e *t) Binnode *temp; if(t) Exchange1(t- temp=t- t-lchild=t-rchild=temp;/*非递归法将二叉树的左右子树互换*/void Exchange2(Binnode *t) while(t|top) stop+=t; t=s-top-/*递归法求叶子结点个数*/int Leaves_Num1(Binnode *t) if(t-lchild=NULL&t-rchild=NULL) return 1; return (Leaves_Num1(t-lchild)+Leaves_Num1(t-rchild); else return 0;/*
12、非递归法求叶子结点个数*/int Leaves_Num2(Binnode *t) int count=0,top=0; while(t|top count+;/*输出叶子结点*/ return count;int main() Binnode *proot=NULL; int p,q;1.CreateBitree:proot); /*建立二叉树时,无左右孩子的结点输入0值*/n2.Output Digui PreOrder: Preorder1(proot);n3.Output Not Digui PreOrder: preorder2(proot);n4.Output Digui InOrd
13、er: Inorder1(proot);n5.Output Not Digui InOrder: Inorder2(proot);n6.Output Digui PostOrder: Posorder1(proot);n7.Output Not Digui PostOrder: Posorder2(proot);n8.Output LevelOrde: Levelorder(proot); Exchange1(proot);n9.Output Digui Exchange: Exchange2(proot);n10.Output Not Digui Exchange:n11.Leaves_No
14、de: q=Leaves_Num2(proot);n12.Output Not Digui Leaves_Num:%dn,q); p=Leaves_Num1(proot);13.Output Digui Leaves_Num:,p);nThis System Once Againn return 0;【思考题】【调试说明】(1)建立二叉树时,必须按先序遍历方式依次输入结点值(该程序中为字符)。当输入叶子结点时,它的左右子树为空以输入“0”值作为结束。(2)该程序集中了二叉树操作的常用算法,根据需要可以在此基础上进行裁剪,只实现其中一种即可,并调试运行。 当用二叉链表作为二叉树的存储结构时,因为
15、每个结点中只有指向其左、右孩子结点的指针,所以从任一结点出发只能直接找到该结点的左、右孩子。在一般情况下靠它无法直接找到该结点在某种遍历次序下的前驱和后继结点。如果在每个结点中增加指向其前驱和后继结点的指针,将降低存储空间的效率。与此同时,我们可以证明:在n个结点的二叉链表中含有n+1个空指针。因为含n个结点的二叉链表中含有2n个指针,除了根结点,每个结点都有一个从父结点指向该结点的指针,因此一共使用了n-1个指针,所以在n个结点的二叉链表中含有2n-(n-1)=n+1个空指针。因此,可以利用这些空指针,存放指向结点在某种遍历次序下的前驱和后继结点的指针。这种附加的指针称为线索,加上了线索的二
16、叉链表称为线索链表,相应的二叉树称为线索二叉树。为了区分一个结点的指针是指向其孩子的指针,还是指向其前驱或后继结点的线索,可在每个结点中增加两个线索标志。这样,线索二叉树结点类型定义为:LchildLtagDataRtagRchild其中:1. Ltag=0时,表示Lchild指向该结点的左孩子;2. Ltag=1时,表示Lchild指向该结点的线性前驱结点;3. Rtag=0时,表示Rchild指向该结点的右孩子;4. Rtag=1时,表示Rchild指向该结点的线性后继结点;以二叉链表结点数据结构所构成的二叉链表作为二叉树的存储结构,叫做线索二叉链表;指向结点的线性前驱或者线性后继结点的指
17、针叫做线索;加上线索的二叉树称为线索二叉树;对二叉树以某种次序遍历将其变为线索二叉树的过程叫做线索化。中序线索化是指用二叉链表结点数据结构建立二叉树的二叉链表,然后按照中序遍历的方法访问结点时建立线索。例如有如上图所示二叉树,则中序遍历的顺序是:O / J * I + H A G【参考程序】typedef enumLink,Thread PointerTag; /*指针标志*/typedef char DataType;typedef struct BiThreTree /*定义结点元素*/ PointerTag LTag,RTag; DataType data; struct BiThreT
18、ree *lchild,*rchild; BiThreTree;BiThreTree *pre; /*全局变量,用于二叉树的线索化*/BiThreTree *CreateTree() /*按前序输入建立二叉树*/ BiThreTree *T; DataType ch; if(ch=#) T=NULL; T=(BiThreTree *)malloc(sizeof(BiThreTree); T-LTag=Link; /*初始化时指针标志均为Link*/RTag=Link;lchild=CreateTree();rchild=CreateTree(); return T;void InThread(
19、BiThreTree *T) BiThreTree *p; p=T; if(p) InThread(p-p-lchild) p-LTag=Thread; p-lchild=pre;pre-rchild) pre-RTag=Thread; pre-rchild=p; pre=p;BiThreTree *InOrderThrTree(BiThreTree *T) /*中序线索化二叉树*/ BiThreTree *Thre; /*Thre为头结点的指针*/ Thre=(BiThreTree *)malloc(sizeof(BiThreTree); Thre-lchild=T;rchild=Thre; pre=Thre; InThread(T);rchild=pre; return Thre;void I
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1