层次遍历Word格式文档下载.docx
《层次遍历Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《层次遍历Word格式文档下载.docx(34页珍藏版)》请在冰豆网上搜索。
![层次遍历Word格式文档下载.docx](https://file1.bdocx.com/fileroot1/2023-2/5/c37c0997-3af0-4483-8344-a1d9df10dcdc/c37c0997-3af0-4483-8344-a1d9df10dcdc1.gif)
printf("
\n"
);
为了保证唯一地构造出所希望的二叉树,在键入这棵树的先序序列时,需要在所有空二叉
树的位置上填补一个特殊的字符,比如,'
'
。
在算法中,需要对每个输入的字符进行判
断,如果对应的字符是'
,则在相应的位置上构造一棵空二叉树;
否则,创建一个新结
点。
整个算法结构以先序遍历递归算法为基础,二叉树中结点之间的指针连接是通过指针
参数在递归调用返回时完成。
intcreatebitree(bitree&
T,int&
sum)
charch;
scanf("
%c"
&
ch);
if(ch=='
)
T=NULL;
else
if(!
(T=(bitree)malloc(sizeof(binode))))
return0;
T->
data=ch;
sum++;
createbitree(T->
lchild,sum);
rchild,sum);
return1;
具体实现过程为:
#include<
stdio.h>
malloc.h>
typedefstructbinode
chardata;
structbinode*lchild,*rchild;
}binode,*bitree;
//定义树结点结构
typedefstructqueuenode
bitreech;
structqueuenode*next;
}queuenode,*queueptr;
//定义队列结点结构
typedefstruct
queueptrfront;
queueptrrear;
}linkqueue;
//定义队列指针
//建树
}//初始化一个带头结点的队列
voidinitqueue(linkqueue&
q)
q.front=q.rear=(queueptr)malloc(sizeof(queuenode));
q.front->
next=NULL;
//入队列
voidenqueue(linkqueue&
q,bitreep)
queueptrs;
intfirst=1;
s=(queueptr)malloc(sizeof(queuenode));
s->
ch=p;
q.rear->
next=s;
q.rear=s;
//出队列
voiddequeue(linkqueue&
q,bitree&
p)
s=q.front->
next;
p=s->
ch;
data=p->
data;
next=s->
if(q.rear==s)
q.rear=q.front;
free(s);
%c"
data);
}//判断队列是否为空
intqueueempty(linkqueueq)
if(q.front->
next==NULL)
}//按层次遍历树中结点
//主函数
voidmain()
intn=0;
bitreebt;
createbitree(bt,n);
该二叉树共有%d个结点.\n"
n);
按层次遍历树中结点其输出顺序为:
\n"
traverse(bt);
通过上机实践,帮助学生进一步掌握指针变量和动态变量的含义,掌握二叉树的结构特性,以及各种存储结构的特点及适用范围,掌握用指针类型描述、访问和处理二叉树的运算。
【实验内容】
实验题目一:
层序遍历二叉树
【实验步骤】
1已知二叉树以二叉链表作为存储结构,写一个算法按层序遍历它,通过程序在终端屏幕上打印出它的层序序列。
2先建立二叉树的二叉链表存储结构,再遍历它。
3利用队列完成算法。
编程实现以二叉链表存储的二叉树的中序遍历的非递归算法。
编程实现二叉树的中序线索链表的生成(线索化)及其遍历的算法。
实验题目二:
交换二叉树的所有结点的左右子树
1已知二叉树以二叉链表作为存储结构,写一个算法交换该二叉树的所有结点的左右子树。
2先建立二叉树的二叉链表存储结构,再完成算法,注意结果的输出形式!
3利用栈。
可设二叉树的根指针为t,且以二叉链表表示,可利用一个指针栈来实现,且设栈单元包括数据域和指针域,当树非空时,将当前的树根结点进栈,同时将当前栈顶元素出栈当作根结点,然后依据当前的根结点是否具有孩子结点来判定是否将其左右指针交换;
再将交换后的左指针或右指针入栈,如此反复,直到栈空。
【程序说明】
该程序集成了如下功能:
(1)二叉树的建立
(2)递归和非递归先序,中序和后序遍历二叉树
(3)按层次遍历二叉树
(4)交换二叉树的左右子树
(5)输出叶子结点
(6)递归和非递归计算叶子结点的数目
#include<
stdlib.h>
conio.h>
math.h>
typedefstructBinnode{
chardata;
structBinnode*lchild;
structBinnode*rchild;
}Binnode;
/*按照前序遍历建立二叉树*/
voidCreat_Bintree(Binnode**t)
charch;
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)->
right"
Creat_Bintree(&
}
/*按照前序递归遍历二叉树*/
voidPreorder1(Binnode*t)
if(t!
t->
data);
Preorder1(t->
/*按照中序递归遍历二叉树*/
voidInorder1(Binnode*t)
{/*printf("
\n输出中序递归遍历序列:
"
*/
Inorder1(t->
/*按照后序递归遍历二叉树*/
voidPosorder1(Binnode*t)
\n输出后序递归遍历序列:
Posorder1(t->
/*按照前序非递归遍历二叉树*/
voidpreorder2(Binnode*root)/*先序非递归遍历二叉树*/
{Binnode*p,*stack[100];
inttop;
p=root;
if(root!
{top=1;
stack[top]=p;
while(top>
0)
p=stack[top];
/*将右小孩放入栈*/
top--;
p->
if(p->
{top++;
stack[top]=p->
rchild;
lchild;
/*按照中序非递归遍历二叉树*/
voidInorder2(Binnode*root)/*中序非递归遍历二叉树*/
inttop=0;
do{
while(p!
top++;
p=p->
if(top>
p=stack[top];
/*p所指的节点为无左子树或其左子树已经遍历过*/
}while(p!
=NULL||top!
=0);
/*按照后序非递归遍历二叉树*/
voidPosorder2(Binnode*t)
Binnode*s[100];
inttop=-1;
intflag[100];
while(t!
=-1)
while(t)
flag[top]=0;
s[top]=t;
t=t->
=0&
&
flag[top]==1)
t=s[top];
=0)
flag[top]=1;
t=NULL;
/*按照层次遍历二叉树*/
intfront=0,rear=1;
voidLevelorder(Binnode*t)
Binnode*q[100];
q[0]=t;
/*intfront=0,rear=1;
while(front<
rear)
if(q[front])
q[front]->
q[rear++]=q[front]->
front++;
/*递归法将二叉树的左右子树互换*/
voidExchange1(Binnode*t)
Binnode*temp;
if(t)
Exchange1(t->
temp=t->
t->
lchild=t->
rchild=temp;
/*非递归法将二叉树的左右子树互换*/
voidExchange2(Binnode*t)
while(t||top)
s[top++]=t;
t=s[--top]->
/*递归法求叶子结点个数*/
intLeaves_Num1(Binnode*t)
if(t->
lchild==NULL&
t->
rchild==NULL)
return1;
return(Leaves_Num1(t->
lchild)+Leaves_Num1(t->
rchild));
elsereturn0;
/*非递归法求叶子结点个数*/
intLeaves_Num2(Binnode*t)
intcount=0,top=0;
while(t||top>
count++;
/*输出叶子结点*/
returncount;
intmain()
Binnode*proot=NULL;
intp,q;
1.CreateBitree:
proot);
/*建立二叉树时,无左右孩子的结点输入’0’值*/
\n2.OutputDiguiPreOrder:
Preorder1(proot);
\n3.OutputNotDiguiPreOrder:
preorder2(proot);
\n4.OutputDiguiInOrder:
Inorder1(proot);
\n5.OutputNotDiguiInOrder:
Inorder2(proot);
\n6.OutputDiguiPostOrder:
Posorder1(proot);
\n7.OutputNotDiguiPostOrder:
Posorder2(proot);
\n8.OutputLevelOrde:
Levelorder(proot);
Exchange1(proot);
\n9.OutputDiguiExchange:
Exchange2(proot);
\n10.OutputNotDiguiExchange:
\n11.Leaves_Node:
q=Leaves_Num2(proot);
\n12.OutputNotDiguiLeaves_Num:
%d\n"
q);
p=Leaves_Num1(proot);
13.OutputDiguiLeaves_Num:
p);
\nThisSystemOnceAgain\n"
return0;
【思考题】
【调试说明】
(1)建立二叉树时,必须按先序遍历方式依次输入结点值(该程序中为字符)。
当输入叶子结点时,它的左右子树为空以输入“0”值作为结束。
(2)该程序集中了二叉树操作的常用算法,根据需要可以在此基础上进行裁剪,只实现其中一种即可,并调试运行。
当用二叉链表作为二叉树的存储结构时,因为每个结点中只有指向其左、右孩子结点的指针,所以从任一结点出发只能直接找到该结点的左、右孩子。
在一般情况下靠它无法直接找到该结点在某种遍历次序下的前驱和后继结点。
如果在每个结点中增加指向其前驱和后继结点的指针,将降低存储空间的效率。
与此同时,我们可以证明:
在n个结点的二叉链表中含有n+1个空指针。
因为含n个结点的二叉链表中含有2n个指针,除了根结点,每个结点都有一个从父结点指向该结点的指针,因此一共使用了n-1个指针,所以在n个结点的二叉链表中含有2n-(n-1)=n+1个空指针。
因此,可以利用这些空指针,存放指向结点在某种遍历次序下的前驱和后继结点的指针。
这种附加的指针称为线索,加上了线索的二叉链表称为线索链表,相应的二叉树称为线索二叉树。
为了区分一个结点的指针是指向其孩子的指针,还是指向其前驱或后继结点的线索,可在每个结点中增加两个线索标志。
这样,线索二叉树结点类型定义为:
Lchild
Ltag
Data
Rtag
Rchild
其中:
1.Ltag=0时,表示Lchild指向该结点的左孩子;
2.Ltag=1时,表示Lchild指向该结点的线性前驱结点;
3.Rtag=0时,表示Rchild指向该结点的右孩子;
4.Rtag=1时,表示Rchild指向该结点的线性后继结点;
以二叉链表结点数据结构所构成的二叉链表作为二叉树的存储结构,叫做线索二叉链表;
指向结点的线性前驱或者线性后继结点的指针叫做线索;
加上线索的二叉树称为线索二叉树;
对二叉树以某种次序遍历将其变为线索二叉树的过程叫做线索化。
中序线索化是指用二叉链表结点数据结构建立二叉树的二叉链表,然后按照中序遍历的方法访问结点时建立线索。
例如有如上图所示二叉树,则中序遍历的顺序是:
O/J*I+HAG
【参考程序】
typedefenum{Link,Thread}PointerTag;
/*指针标志*/
typedefcharDataType;
typedefstructBiThreTree{/*定义结点元素*/
PointerTagLTag,RTag;
DataTypedata;
structBiThreTree*lchild,*rchild;
}BiThreTree;
BiThreTree*pre;
/*全局变量,用于二叉树的线索化*/
BiThreTree*CreateTree()/*按前序输入建立二叉树*/
BiThreTree*T;
DataTypech;
if(ch==’#’)
T=NULL;
{T=(BiThreTree*)malloc(sizeof(BiThreTree));
T->
LTag=Link;
/*初始化时指针标志均为Link*/
RTag=Link;
lchild=CreateTree();
rchild=CreateTree();
returnT;
voidInThread(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;
returnThre;
voidI