这个作业属于哪个课程 | https://edu.cnblogs.com/campus/qdu/DS2020 |
---|---|
这个作业的要求在哪里 | https://edu.cnblogs.com/campus/qdu/DS2020/homework/11165 |
这个作业的目标 | |
** 学号** |
一、 实验目的
- 掌握二叉树的基本特性
- 掌握二叉树的先序、中序、后序的递归遍历算法
- 理解二叉树的先序、中序、后序的非递归遍历算法
- 通过求二叉树的深度、叶子结点数和层序遍历等算法,理解二叉树的基本特性
二、 实验预习
说明以下概念
1. 二叉树(Binary Tree):
它是n(n>=0)个结点的有限集,它或者是空集(n=0),或者由一个根结点及两棵互不相交的、分别称作这个根的左子树和右子树的二叉树组成。
链接:https://blog.csdn.net/a951273629/article/details/107094551
2. 递归遍历(Recursive Traversal):
(递归)它是利用计算机堆栈的概念,一般通过调用相同的函数来实现,函数中一般会设置终止的语句。(遍历)对于集合数据而言,访问所有的数据即为遍历。遍历的方法可以分为递归或者迭代。
链接:https://zhidao.baidu.com/question/180436257.html
3. 非递归遍历(Non-recursive Traversal):
要想采用非递归的方法遍历树,又不借助于前面的队列与栈,我们需要该树是一棵可回溯的二叉树,即从子节点要知道他的父结点及祖先结点,与前面的二叉树不同的是,树的结点结构体中多一个指向父的结点指针,这样外界可以以非递归的方式来遍历二叉树了。
https://blog.csdn.net/wangweixaut061/article/details/7173880
4. 层序遍历(Sequence Traversal):
进行层序遍历时,对某一层的结点访问完后,再按照它们的访问次序对各个结点的左孩子和右孩子顺序访问,这样一层一层进行,先访问的结点其左右孩子也要先访问,这正好符合队列的操作特性。
链接:https://blog.csdn.net/chijiang9575/article/details/100796224
注:1.每个链接有对应的概念介绍及扩展知识(分类、使用等);2.上述均不是超链接,仅仅是名称。
三、 实验内容和要求
- 阅读并运行下面程序,根据输入写出运行结果,并画出二叉树的形态。
#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###
运行结果:
二叉树形态:
- 在上题中补充求二叉树中求结点总数算法(提示:可在某种遍历过程中统计遍历的结点数),并在主函数中补充相应的调用验证正确性。
算法代码:
#include<malloc.h>
#include<iostream>
#include<conio.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 PreOrder_num(BiTree p) {
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;
}
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);
printf("\n\n结点总数:");
printf("%d",PreOrder_num(t));
release(t);
return 0;
}
运行结果:
- 在上题中补充求二叉树中求叶子结点总数算法(提示:可在某种遍历过程中统计遍历的叶子结点数),并在主函数中补充相应的调用验证正确性。
算法代码:
int num1=0 ,num2=0;
if(p==NULL)
return 0;
else if(p->lchild==NULL&&p->rchild==NULL)
return 1;
else{
num1=LeafNodes(p->lchild) ;
num2=LeafNodes(p->rchild) ;
return (num1+num2);
}
}
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);
printf("\n\n结点总数:");
printf("%d",PreOrder_num(t));
printf("\n\n叶结点总数:");
printf("%d",LeafNodes(t));
release(t);
return 0;
}
运行结果:
- 在上题中补充求二叉树深度算法,并在主函数中补充相应的调用验证正确性。
算法代码:
int lchilddep,rchilddep;
if(p==NULL)
return 0;
else {
lchilddep=BTNodeDepth(p->lchild);
rchilddep=BTNodeDepth(p->rchild);
return(lchilddep>rchilddep)?(lchilddep+1):(rchilddep+1);
}
}
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);
printf("\n\n结点总数:");
printf("%d",PreOrder_num(t));
printf("\n\n树的深度:");
printf("%d",BTNodeDepth(t));
release(t);
return 0;
}
运行结果:
)
四、 实验小结
本实验首先对二叉树基本特性、二叉树的先序、中序、后序的递归遍历算法 、二叉树的先序、中序、后序的非递归遍历算法、二叉树的深度、叶子结点数和层序遍历等算法,理解二叉树的基本特性等知识点进行系统性的学习,并对相应的算法有了初步的了解,整体上还不错。但算法的实现有待提升。
五、 评语