第六次作业
|这个作业属于哪个课程|https://edu.cnblogs.com/campus/qdu/DS2020|
|这个作业要求在哪里|https://edu.cnblogs.com/campus/qdu/DS2020/homework/11430|
|这个作业的目标|掌握理解二叉树基本特性,遍历算法|
|学号| 2018204291 |
一、实验目的
1、掌握二叉树的基本特性
2、掌握二叉树的先序、中序、后序的递归遍历算法
3、理解二叉树的先序、中序、后序的非递归遍历算法
4、通过求二叉树的深度、叶子结点数和层序遍历等算法,理解二叉树的基本特性
二、实验预习
说明以下概念
1、二叉树:
二叉树是指树中节点的度不大于2的有序树,它是一种最简单且最重要的树。二叉树的递归定义为:二叉树是一棵空树,或者是一棵由一个根节点和两棵互不相交的,分别称作根的左子树和右子树组成的非空树;左子树和右子树又同样都是二叉树。
2、递归遍历:
递归先序遍历二叉树的操作定义为:访问根结点,先序遍历左子树,先序遍历右子树。递归中序遍历二叉树的操作定义为:中序序遍历左子树,访问根结点,中序遍历右子树。递归后序遍历二叉树的操作定义为:后序遍历左子树,后序遍历右子树,访问根结点。
3、非递归遍历:
根据前序遍历访问的顺序,优先访问根结点,然后再分别访问左孩子和右孩子。即对于任一结点,其可看做是根结点,因此可以直接访问,访问完之后,若其左孩子不为空,按相同规则访问它的左子树;当访问其左子树时,再访问它的右子树。
根据中序遍历的顺序,对于任一结点,优先访问其左孩子,而左孩子结点又可以看做一根结点,然后继续访问其左孩子结点,直到遇到左孩子结点为空的结点才进行访问,然后按相同的规则访问其右子树。
根据后序遍历的顺序,对于任一结点P,将其入栈,然后沿其左子树一直往下搜索,直到搜索到没有左孩子的结点,此时该结点出现在栈顶,但是此时不能将其出栈并访问,因此其右孩子还为被访问。所以接下来按照相同的规则对其右子树进行相同的处理,当访问完其右孩子时,该结点又出现在栈顶,此时可以将其出栈并访问。这样就保证了正确的访问顺序。可以看出,在这个过程中,每个结点都两次出现在栈顶,只有在第二次出现在栈顶时,才能访问它。因此需要多设置一个变量标识该结点是否是第一次出现在栈顶。
4、层序遍历:
设二叉树的根节点所在层数为1,层序遍历就是从所在二叉树的根节点出发,首先访问第一层的树根节点,然后从左到右访问第2层上的节点,接着是第三层的节点,以此类推,自上而下,自左至右逐层访问树的结点的过程就是层序遍历
三、实验内容和要求
1、阅读并运行下面程序,根据输入写出运行结果,并画出二叉树的形态。
include<stdio.h>
include<malloc.h>
define MAX 20
typedef struct BTNode{ /节点结构声明/
char data ; /节点数据/
struct BTNode lchild;
struct BTNode rchild ; /指针/
}*BiTree;
void createBiTree(BiTree t){ / 先序遍历创建二叉树/
char s;
BiTree q;
printf("\nplease input data:(exit for #)");
s=getche();
if(s=='#'){t=NULL; return;}
q=(BiTree)malloc(sizeof(struct BTNode));
if(q==NULL){printf("Memory alloc failure!"); exit(0);}
q->data=s;
t=q;
createBiTree(&q->lchild); /递归建立左子树/
createBiTree(&q->rchild); /递归建立右子树*/
}
void PreOrder(BiTree p){ /* 先序遍历二叉树/
if ( p!= NULL ) {
printf("%c", p->data);
PreOrder( p->lchild ) ;
PreOrder( p->rchild) ;
}
}
void InOrder(BiTree p){ / 中序遍历二叉树/
if( p!= NULL ) {
InOrder( p->lchild ) ;
printf("%c", p->data);
InOrder( p->rchild) ;
}
}
void PostOrder(BiTree p){ / 后序遍历二叉树*/
if ( p!= NULL ) {
PostOrder( p->lchild ) ;
PostOrder( p->rchild) ;
printf("%c", p->data);
}
}
void Preorder_n(BiTree p){ /先序遍历的非递归算法/
BiTree stack[MAX],q;
int top=0,i;
for(i=0;i<MAX;i++) stack[i]=NULL;/初始化栈/
q=p;
while(q!=NULL){
printf("%c",q->data);
if(q->rchild!=NULL) stack[top++]=q->rchild;
if(q->lchild!=NULL) q=q->lchild;
else
if(top>0) q=stack[--top];
else q=NULL;
}
}
void release(BiTree t){ /释放二叉树空间/
if(t!=NULL){
release(t->lchild);
release(t->rchild);
free(t);
}
}
int main(){
BiTree t=NULL;
createBiTree(&t);
printf("\n\nPreOrder the tree is:");
PreOrder(t);
printf("\n\nInOrder the tree is:");
InOrder(t);
printf("\n\nPostOrder the tree is:");
PostOrder(t);
printf("\n\n先序遍历序列(非递归)😊;
Preorder_n(t);
release(t);
return 0;
}
运行程序
输入:
ABC##DE#G##F###
运行结果:
PreOrder the tree is:ABCDEGF
InOrder the tree is:CBEGDFA
PostOrder the tree is:CGEFDBA
无序遍历序列:ABCDEGF
2、在上题中补充求二叉树中求结点总数算法(提示:可在某种遍历过程中统计遍历的结点数),并在主函数中补充相应的调用验证正确性。
算法代码:
int j=0;
BiTree stack[MAX],q;
int top=0,i;
for(i=0; i<MAX; i++) stack[i]=NULL; /初始化栈/
q=p;
while(q!=NULL) {
j++;
if(q->rchild!=NULL) stack[top++]=q->rchild;
if(q->lchild!=NULL) q=q->lchild;
else
if(top>0) q=stack[--top];
else q=NULL;
}
return j;
运行结果:
ProOrder the is:ABCDEGF
InOrder the is:CEGDFA
PostOrder the is:CGEFDBA
先序遍历序列:ABCDEGF
节点数:7
3、在上题中补充求二叉树中求叶子结点总数算法(提示:可在某种遍历过程中统计遍历的叶子结点数),并在主函数中补充相应的调用验证正确性。
算法代码:
int num1=0 ,num2=0;
if(pNULL)
return 0;
else if(p->lchildNULL&&p->rchild==NULL)
return 1;
else
{
num1=LeafNodes(p->lchild) ;
num2=LeafNodes(p->rchild) ;
return (num1+num2);
}
运行结果:
PreOrder the is:ABCDEGF
InOrder the is:CBEGDFA
PostOrder the is:CGEFDBA
先序遍历序列:ABCDEGF
节点总数:7
叶结点数:3
4、在上题中补充求二叉树深度算法,并在主函数中补充相应的调用验证正确性。
算法代码:
int lchilddep,rchilddep;
if(p==NULL)
return 0;
else {
lchilddep=BTNodeDepth(p->lchild);
rchilddep=BTNodeDepth(p->rchild);
return(lchilddep>rchilddep)?(lchilddep+1):(rchilddep+1);
}
运行结果:
PreOrder the tree is:ABCDEGF
InOrder the tree is:CBEGDFA
PostOreder the tree is:CGEFDBA
先序遍历序列:ABCDEGF
节点数:7
叶结点数:3
树的深度:5
选做实验:(代码可另附纸)
4、 补充二叉树层次遍历算法。(提示:利用队列实现)
5、补充二叉树中序、后序非递归算法。
四、实验小结:
通过实验,了解了二叉树的基本特性,熟练掌握了二叉树的先序、中序、后序的递归遍历算法,并且认识了解了求二叉树的深度、叶子结点数和层序遍历等算法。
浙公网安备 33010602011771号