树和二叉树层序遍历二叉树Word下载.docx
《树和二叉树层序遍历二叉树Word下载.docx》由会员分享,可在线阅读,更多相关《树和二叉树层序遍历二叉树Word下载.docx(26页珍藏版)》请在冰豆网上搜索。
![树和二叉树层序遍历二叉树Word下载.docx](https://file1.bdocx.com/fileroot1/2022-11/27/08f978f1-d5db-4d35-aba7-ec345a308d80/08f978f1-d5db-4d35-aba7-ec345a308d801.gif)
if(ch=='
0'
)*t=NULL;
else
*t=(Binnode*)malloc(sizeof(Binnode));
if(!
*t)exit(OVERFLOW);
(*t)->
data=ch;
printf("
%c:
left"
ch);
Creat_Bintree(&
lchild);
right"
Creat_Bintree(&
rchild);
}
/*按照前序递归遍历二叉树*/
voidPreorder1(Binnode*t)
if(t!
=NULL)
%c"
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->
rchild!
{top++;
stack[top]=p->
rchild;
lchild!
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&
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:
\n"
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;
else
{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;
lchild=pre;
pre->
rchild)
{pre->
RTag=Thread;
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;
voidInThrTravel(BiThreTree*Thre)/*中序遍历二叉树*/
p=Thre->
=Thre)/*指针回指向头结点时结束*/
while(p->
LTag==Link)
%4c"
RTag==Thread&
=Thre)
{p=p->
voidmain()
BiThreTree*T,*Thre;
printf(“PreOrderCreateBinaryTree:
\n”);
T=CreateTree();
Thre=InOrderThrTree(T);
printf(“InOrderTraverseBinaryTree:
InThrTravel(Thre);
system("
pause"
【调试举例】
(1)建立二叉树时,按先序遍历方式输入:
“ABD##EH##I##CF##G##”,其中“#”表示空指针。
(2)建立的二叉树为:
A
BC
DEFG
HI
(3)程序输出为中序遍历线索化二叉树的结果:
DBHEIAFCG
已知A、B和C为三个递增有序的线性表,现要求对A表作如下操作:
删除那些既在B表中出现又在C表中出现的元素。
1.试对顺序表编写实现上述操作的算法并上机编写代码,要求算法尽可能高效。
在实验报告中分析你的算法的时间复杂度。
2.A表中要删除的元素实际上就是在三个表中都存在的元素。
注意这三个线性表都是递增有序的线性表!
可以利用这一性质减少对线性表“扫描”的趟数。
3.改用单链表作为存储结构编写算法,请释放A表中无用的结点空间,并上机编程实现。
【算法思想】
先从B和C中找出共有元素same,再从A中从当前位置开始,凡小于same的元素均保留,等于same的就跳过,大于same时就再找下一个same。
【顺序存储结构算法描述】
voidSqList_Delete(SqList&
A,SqListB,SqListC)
i=0;
j=0;
m=0;
/*i指示A中元素原来的位置,m为移动后的位置*/
while(i<
A.length&
j<
B.length&
k<
C.length)
if(B.elem[j]<
C.elem[k])j++;
elseif(B.elem[j]>
C.elem[k])k++;
else{
same=B.elem[j];
/*找到了相同元素same*/
while(B.elem[j]==same)j++;
while(C.elem[k])==same)k++;
/*j,k后移到新的元素*/
A.elem[i]<
same)
A.elem[m++]=A.elem[i++];
/*需要保留的元素移动到新位置*/
while(i<
A.elem[i]==same)i++;
}/*else*/
}/*while*/
A.length)
/*A的剩余元素重新存储*/
A.length=m;
}/*SqList_Delete*/
【顺序存储结构参考程序】
#include<
main()
#defineN3/*宏定义,代表数组维数*/
#defineM4
#defineT5
inti,j,k,r,m,same;
/*定义变量分别指向数组a,b,c*/
inta[N],b[M],c[T];
printf(“pleaseinputnumbers:
for(i=0;
i<
N;
i++)scanf("
%d"
a[i]);
for(j=0;
M;
j++)scanf("
b[j]);
for(k=0;
T;
k++)scanf("
c[k]);
k=0;
/*分别赋值为0,即指向数组的第一元素*/
N&
M&
T)
if(b[j]<
c[k])j++;
elseif(b[j]>
c[k])k++;
same=b[j];
while(b[j]==same)j++;
while(c[k]==same)k++;
a[i]<
a[m++]=a[i++];
a[i]==same)i++;
N)
a[%d]={"
m);
/*输出删除元素后的数组a/*
for(r=0;
r<
m-1;
r++)printf("
%d,"
a[r]);
a[m-1]);
}\n"
return;
【程序调试】
程序运行是屏幕显示:
pleaseinputnumbers:
此时输入三组测试数据,数据间用空格隔开:
234回车
3456回车
45678回车
程序输出结果:
a[3]={2,3},即删除了数组a中即在b和c中都出现的元素。
【单链表存储结构参考程序】
#include<
TypedefstructLNode{
intdata;
structLNode*next;
}Lnode,*LinkList;
/*定义链表节点的结构*/
voidmain()
{/*功能:
建立单链表A,B,C,并且删除A中均在B和C中出现的数据。
CreateList(LinkListhead);
/*函数声明*/
ListDelete(LinkListLa,LinkListLb,LinkListLc);
Print(LinkListhead);
LinkListheadA,headB,headC;
headA=NULL;
headB=NULL;
headC=NULL;
headA=CreateList(headA);
/*建立链表*/
headB=CreateList(headB);
headC=CreateList(headC);
print(headA);
/*输出显示链表数据*/
print(headB);
print(headC);
headA=ListDelete(headA,headB,headC);
/*删除A中满足条件的节点*/
Print(headA);
LinkListcreateList(LinkListhead)
建立有头节点head的数据单链表*/
LinkListp,q;
p=q=(LinkList)malloc(sizeof(Ln