实验四 二叉树的操作
班级:计算机1002班
姓名:**
学号:**
完成日期:20XX.6.14
题目:对于给定的一二叉树,实现各种约定的遍历。
一、实验目的:
(1)掌握二叉树的定义和存储表示,学会建立一棵特定二叉树的方法;
(2)掌握二叉树的遍历算法(先序、中序、后序遍历算法)的思想,并学会遍历算法的递归实现和非递归实现。
二、实验内容:构造二叉树,再实现二叉树的先序、中序、后序遍历,最后统计二叉树的深度。
三、实验步骤:
(一) 需求分析
1. 二叉树的建立首先要建立一个二叉链表的结构体,包含根节点和左右子树。因为树的每一个左右子树又是一颗二叉树,所以用递归的方法来建立其左右子树。二叉树的遍历是一种把二叉树的每一个节点访问并输出的过程,遍历时根结点与左右孩子的输出顺序构成了不同的遍历方法,这个过程需要按照不同的遍历的方法,先输出根结点还是先输出左右孩子,可以用选择语句来实现。
2.程序的执行命令为:
1)构造结点类型,然后创建二叉树。
2)根据提示,从键盘输入各个结点。
3)通过选择一种方式(先序、中序或者后序)遍历。
4)输出结果,结束。
(二)概要设计
1.二叉树的二叉链表结点存储类型定义
typedef struct Node
{
DataType data;
struct Node *LChild;
struct Node *RChild;
}BitNode,*BitTree;
2.建立如下图所示二叉树:void CreatBiTree(BitTree *bt)用扩展先序遍历序列创建二叉树,如果是当前树根置为空,否则申请一个新节点。
3.本程序包含四个模块
1) 主程序模块:
2)先序遍历模块
3)中序遍历模块
4)后序遍历模块
4.模块调用关系:
主程序模块
(三)详细设计
1.建立二叉树存储类型
//==========构造二叉树=======
void CreatBiTree(BitTree *bt)//用扩展先序遍历序列创建二叉树,如果是当前树根置为空,否则申请一个新节点//
{
char ch;
ch=getchar();
if(ch=='.')*bt=NULL;
else
{
*bt=(BitTree)malloc(sizeof(BitNode));//申请一段关于该节点类型的存储空间
(*bt)->data=ch; //生成根结点
CreatBiTree(&((*bt)->LChild)); //构造左子树
CreatBiTree(&((*bt)->RChild)); //构造右子树
}
}
2. 编程实现以上二叉树的前序、中序和后序遍历操作,输出遍历序列
1)先序遍历二叉树的递归算法如下:
void PreOrder(BitTree root)
{
if (root!=NULL)
{
Visit(root ->data);
PreOrder(root ->LChild); //递归调用核心
PreOrder(root ->RChild);
}
}
2)中序遍历二叉树的递归算法如下:
void InOrder(BitTree root)
{
if (root!=NULL)
{
InOrder(root ->LChild);
Visit(root ->data);
InOrder(root ->RChild);
}
}
3)后序遍历二叉树的递归算法如下:
void PostOrder(BitTree root)
{
if(root!=NULL)
{
PostOrder(root ->LChild);
PostOrder(root ->RChild);
Visit(root ->data);
}
}
4)计算二叉树的深度算法如下:
int PostTreeDepth(BitTree bt) //求二叉树的深度
{
int hl,hr,max;
if(bt!=NULL)
{
hl=PostTreeDepth(bt->LChild); //求左子树的深度
hr=PostTreeDepth(bt->RChild); //求右子树的深度
max=hl>hr?hl:hr; //得到左、右子树深度较大者
return(max+1); //返回树的深度
}
else return(0); //如果是空树,则返回0
}
四、调试分析及测试结果
1. 进入演示程序后的显示主界面:
请输入二叉树中的元素;
先序、中序和后序遍历分别输出结果。
2.测试结果
以扩展先序遍历序列输入,其中.代表空子树:ABC..DE.G..F…
先序遍历序列为:ABCDEGF
中序遍历序列为:CBEGDFA
后序遍历序列为:CGEFDBA
此二叉树的深度为:5
3.程序运行结果
1)输入二叉树中的元素(以扩展先序遍历序列输入,其中.代表空子树),显示截图为:
图一
2)输出结果,显示界面为:
图二
4.调试分析:
本程序通过分别调用先序遍历、中序遍历以及后序遍历函数对二叉树中的元素进行遍历,整个程序基本满足实验要求,但是在一些细节问题上面还是存在缺陷,比如大小写字母不同也会导致程序无法运行,这就需要我们在处理问题上认真细致,还有就是程序并不是很完善,总之,我会在今后更加努力,是程序更完美。
六、实验总结
1. 二叉树对于进行表达式的前缀,中缀和后缀的表示有明显的优势,既方便,又容易理解。其先序,中序和后序分别对应这表达式的前缀,中缀和后缀。
2. 在建树与进行树的遍历的时候一定要理解其建树与遍历的整个过程。不然就会连为什么这样做都不知道。在遍历树的时候最常用到的就是栈的结构了(非递归)。
3.本次实验让我更加了解了哈夫曼树的构造和生成方法,以及如何用顺序结构来存储哈夫曼树及构树过程的信息,如何进行编码、译码。也感知到模块程序设计在大程序设计使用中的普遍性,该实验是最好的证明,通过模块程序设计,能使程序可读可写性明显加强。
通过本次实验,使我初步掌握了二叉树的结构特性以及各种存储的结构的特点和适用范围,掌握了哈夫曼树的定义和思想,初步掌握了用凹入法显示树。不过程序仍有树的显示不够完善的缺点,在今后的学习中,我会不断学习,在学习中注意改变。
附录
源程序清单:
#include<stdio.h>
#include<stdlib.h>
#include <malloc.h>
#include <conio.h>
typedef int DataType;
typedef struct Node //创建结点类型结构体
{
DataType data;
struct Node *LChild;
struct Node *RChild;
}BitNode,*BitTree;
void CreatBiTree(BitTree *bt) //用扩展先序遍历序列创建二叉树,如果是当前树根置为空,否则申请一个新节点//
{
char ch;
ch=getchar();
if(ch=='.')*bt=NULL;
else
{
*bt=(BitTree)malloc(sizeof(BitNode));
(*bt)->data=ch;
CreatBiTree(&((*bt)->LChild));
CreatBiTree(&((*bt)->RChild));
}
}
void visit(char ch)//访问根节点
{
printf("%c",ch);
}
void PreOrder(BitTree root) //先序遍历二叉树的递归算法
{
if (root!=NULL)
{
Visit(root ->data);
PreOrder(root ->LChild);
PreOrder(root ->RChild);
}
}
void InOrder(BitTree root) //中序遍历二叉树的递归算法
{
if (root!=NULL)
{
InOrder(root ->LChild);
Visit(root ->data);
InOrder(root ->RChild);
}
}
void PostOrder(BitTree root) //后序遍历求二叉树的递归算法
{
if(root!=NULL)
{
PostOrder(root ->LChild);
PostOrder(root ->RChild);
Visit(root ->data);
}
}
int PostTreeDepth(BitTree bt) //求二叉树的深度
{
int hl,hr,max;
if(bt!=NULL)
{
hl=PostTreeDepth(bt->LChild); //求左子树的深度
hr=PostTreeDepth(bt->RChild); //求右子树的深度
max=hl>hr?hl:hr; //得到左、右子树深度较大者
return(max+1); //返回树的深度
}
else return(0); //如果是空树,则返回0
}
void main()
{ BitTree T;
int h;
int layer;
int treeleaf;
layer=0;
printf("请输入二叉树中的元素(以扩展先序遍历序列输入,其中.代表空子树):\n"); CreatBiTree(&T);
printf("先序遍历序列为:");
PreOrder(T);
printf("\n中序遍历序列为:");
InOrder(T);
printf("\n后序遍历序列为:");
PostOrder(T);
h=PostTreeDepth(T);
printf("\n");
printf("此二叉树的深度为:%d\n",h);}
第二篇:二叉树链式存储结构 第六章实验报告
实验名称:二叉树链式存储结构
实验类型:验证性实验
班级:**
学号:***
姓名:
实验日期:20XX.5.27
1. 问题描述
二叉链表的C语言描述;
基本运算的算法——建立二叉链表、先序遍历二叉树、中序遍历二叉树、后序遍历二叉树、后序遍历求二叉树深度。
2. 数据结构设计
typedef struct Bitnode
{ char data;
struct Bitnode *lchild,*rchild;
}Bitnode,*Bitree;
3. 算法设计
建立二叉链表:void createBitree(Bitree &T)
{
char ch;
if((ch=getchar())=='#') T=NULL;
else{T=(Bitnode*)malloc(sizeof(Bitnode));
T->data=ch;
createBitree(T->lchild);
createBitree(T->rchild);
}
}
先序遍历二叉树:void preorder(Bitree &T)
{
if(T!=NULL)
{printf("%c",T->data);
preorder(T->lchild);
preorder(T->rchild);}}
中序遍历二叉树:void inorder(Bitree &T)
{if(T!=NULL)
{ inorder(T->lchild);
printf("%c",T->data);
inorder(T->rchild);
}
后序遍历二叉树:void postorder(Bitree &T)
{
if(T!=NULL)
{postorder(T->lchild);
postorder(T->rchild);
printf("%c",T->data);
}
}//后序遍历
后序遍历求二叉树深度:int Depth(Bitree &T)
{//返回深度
int d,dl,dr;
if(!T) d=0;
else {dl=Depth(T->lchild);
dr=Depth(T->rchild);
d=1+(dl>dr?dl:dr) ;
}
return d;
}
4.运行、测试与分析
运行程序,显示菜单,
(1) 如图1.1:
图1.1
(2) 结果图1.2:
图1.2
5.实验收获及思考
在实验过程中学会了调试程序,对于二叉树的相关知识有了不同的认识,不仅仅是抽象上的了。更重要的是懂得了自己写程序的重要性,慢慢养成习惯。
6.源代码
#include<stdio.h>
#include<stdlib.h>
typedef struct Bitnode
{ char data;
struct Bitnode *lchild,*rchild;
}Bitnode,*Bitree;
//建立二叉树
void createBitree(Bitree &T)
{
char ch;
if((ch=getchar())=='#') T=NULL;
else{T=(Bitnode*)malloc(sizeof(Bitnode));
T->data=ch;
createBitree(T->lchild);
createBitree(T->rchild);
}
}
//先序遍历输出结点
void preorder(Bitree &T)
{
if(T!=NULL)
{printf("%c",T->data);
preorder(T->lchild);
preorder(T->rchild);
}
}
void inorder(Bitree &T)
{if(T!=NULL)
{ inorder(T->lchild);
printf("%c",T->data);
inorder(T->rchild);
}
}//中序遍历
void postorder(Bitree &T)
{
if(T!=NULL)
{postorder(T->lchild);
postorder(T->rchild);
printf("%c",T->data);
}
}//后序遍历
//后序遍历求深度
int Depth(Bitree &T)
{//返回深度
int d,dl,dr;
if(!T) d=0;
else {dl=Depth(T->lchild);
dr=Depth(T->rchild);
d=1+(dl>dr?dl:dr) ;
}
return d;
}
int main()
{
printf("**********二叉树链表存储********");
printf("\n1.建立二叉链表\n2.先序遍历\n3.中序遍历\n4.后续遍历\n5.后序遍历求深度\n");
printf("例子:abc##de#g##f###\n");
Bitree T;
printf("输入树的结点:\n");
createBitree(T);
printf("先序为:\n");
preorder(T);
printf("\n中序遍历为:\n");
inorder(T) ;
printf("\n后序为:\n");
postorder( T);
printf("后序求深度:%d\n",Depth(T));
system("pause");
}