实验七 二叉树的其他典型算法及其应用1.docx
《实验七 二叉树的其他典型算法及其应用1.docx》由会员分享,可在线阅读,更多相关《实验七 二叉树的其他典型算法及其应用1.docx(19页珍藏版)》请在冰豆网上搜索。
实验七二叉树的其他典型算法及其应用1
实验七二叉树的其他典型算法及其应用
1、实验目的
1、深入了解二叉树递归遍历算法的执行过程,熟练掌握二叉树先序非递归遍历算法、中序非递归算法及其应用。
2、掌握二叉树顺序存储结构、二叉链表结构和静态三叉链表结构的特点与适用范围。
3、掌握哈弗曼树及其应用。
4、掌握树的常用存储结构。
2、实验内容和要求
1、设计并验证如下算法:
输入一颗二叉树的广义表形式,建立该二叉树的二叉链表结构,并求其部结点数目。
例如,对“12.7.4参考源程序”所示二叉树,按下列形式读入字符:
C(E(I,(,J)),f(,G(K,H)))#。
2、哈弗曼编\译码器。
要求根据给定的权值,构建哈弗曼树、实现哈弗曼编码和译码。
3、实验过程及结果
(第一题)
1、需求分析
1、构成广义表的合法字符:
小写或大写字母、空白字符、圆括弧和逗号,且设广义表的原子为单个字符。
2、演示程序以用户和计算机的对话方式执行,广义表的建立方式为边输入边建立;
分解操作的进行方式为,每次输入整个一个命令,按回车然后显示每一个操作的结果。
3、程序执行的命令:
1)建立广义表,提示用户输入广义表字符串;
2)多种方式遍历所建立的树,创建完成后每输入一次命令后在计算机终端显示每一次遍历的结果。
3)求所建树其部结点数;
4)求所建树的高度。
4、输入过程中能自动滤去合法字符以外的其他字符,并能在输入不当时输出相应的提示信息。
5、测试数据:
1)输入:
输出:
2、概要设计
1、广义表的抽象数据类型定义:
ADTGList{
数据对象:
D={aij|i=1,2,…,m,j=1,2,…,n;
Ai,j∈ElemSet,m和n分别称为矩阵的行数和列数}
数据关系:
R={Row,Col}
Row={|1≤i≤m,1≤j≤n-1}
Col={|1≤i≤m-1,1≤j≤n}
基本操作:
InitBiTree(&BT)
操作结果:
构造空二叉树
CreateBiTree(&BT)
操作结果:
建立二叉树
PreOrder(BT)
初始条件:
二叉树BT已存在
操作结果:
先序遍历
InOrder(BT)
初始条件:
二叉树BT已存在
操作结果:
中序遍历
PostOrder(BT)
初始条件:
二叉树BT已存在
操作结果:
后序遍历
LevelOrder(BT)
初始条件:
二叉树BT已存在
操作结果:
按层次遍历
NRPreOrderOrder(BT)
初始条件:
二叉树BT已存在
操作结果:
先序非递归遍历
NodeNumber(BT)
初始条件:
二叉树BT已存在
操作结果:
求BT的所有结点数
TreeDepth(BT)
初始条件:
二叉树BT已存在
操作结果:
求BT的高度
}ADTGList;
⒊本程序模块结构
1主函数模块
voidmain(){
初始化两颗二叉树;
创建二叉树BT,返回根结点BT;
getchar();
while(继续运行){
目录;
Switch(select){
1.PreOrderTraversal;
2.InOrderTraversal;
3.PostOrderTraversal;
4.LevelOrderTraversal;
5.NRPreOrderTraversal;
6.NodeNumber;
7.TreeDepth;
8.Exit;
scanf("%d",&select);
}
}
}
三、详细设计
1、结点、指针类型
⑴二叉链表的存储结构
typedefcharTElemType;
typedefstructBiTNode{
TElemTypedata;
structBiTNode*lchild,*rchild;//左右孩子指针
}BiTNode,*BiTree;
2、重要算法的伪码:
CreateBiTree(BiTree**BT){
InitStack(&S);
*BT=NULL;
scanf("%c",&ch);
while(ch!
='#'){
switch(ch){
case'(':
Push(&S,&p);flag=1;break;
case',':
flag=0;break;
case')':
Pop(&S,&p);break;
default:
p=(BiNode*)malloc(sizeof(BiNode));
p->lchild=p->rchild=NULL;
p->data=ch;
if(!
(*BT))
*BT=p;
else{
GetTop(S,&e);
if(flag)
e->lchild=p;
else
e->rchild=p;
}break;
}
scanf("%c",&ch);
}
}
TreeDepth(BiTreeBT){
if(!
BT)return0;
elsereturn(max(TreeDepth(BT->lchild),TreeDepth(BT->rchild))+1);
}
NodeNumber(BiTreeBT){
if(!
BT)return0;
elsereturnNodeNumber(BT->lchild)+NodeNumber(BT->rchild)+1;
}
四、调试分析
1、本题难度较低,主要算法在掌握了之后比较容易写出,且递归算法的解题思路比较正确,故本题实验完成比较顺利。
2、整体缺点就是目录没有实现重新建树的功能,也就是运行期间没有实行动态存储管理,想要重新建树须重新运行程序,有一定局限性。
3、用广义表形式创建二叉树算法执行时间依赖于广义表的深度和广度,其时间复杂度的分析比较复杂。
递归算法执行过程中所需栈的空间取决于广义表的深度。
五、用户说明
1、进入演示程序后,首先按提示要求输入广义表,按回车后即显示可进行操作的菜单,根据菜单输入相应的操作序号即可进行相应的操作。
如图所示:
选项:
1--先序遍历2--中序遍历3--后序遍历4--按层次遍历5--中序非递归遍历6--求树高度7--求其部结点数8--退出(按任意键退出)
六、测试结果
七、附录(源代码及部分注释)
#include"stdio.h"
#include"stdlib.h"
#include"conio.h"
#include"string.h"
#defineOK1
#defineERROR0
#defineTRUE1
#defineFALSE0
#defineOVERFLOW-1
#defineINFEASIBLE-2
#defineMax_Tree_SIZE20//最大结点数
#defineSTACK_INIT_SIZE100
#defineSTACKINCRENT10
#defineMAXQSIZE100
typedefintStatus;
typedefcharTElemType;
typedefstructBiTNode{
TElemTypedata;
structBiTNode*lchild,*rchild;//左右孩子指针
}BiNode,*BiTree;
typedefBiTreeSElemType;
typedefBiTreeQElemType;//定义栈中数据元素
//栈模块
typedefstructlnode{
SElemType*base;
SElemType*top;//设两指针便于判断栈是否为空
intstacksize;//栈当前可使用的最大容量
}SqStack;
StatusInitStack(SqStack*S);
StatusDestroyStack(SqStack*S);
StatusStackEmpty(SqStackS);
StatusGetTop(SqStacks,SElemType*e);
StatusPush(SqStack*S,SElemType*e);
StatusPop(SqStack*s,SElemType*e);
StatusStackTraverse(SqStacks);
StatusInitStack(SqStack*S)//初始化栈
{
S->base=(SElemType*)malloc(STACK_INIT_SIZE*sizeof(SElemType));
if(!
S->base)
exit(OVERFLOW);
S->top=S->base;//空栈的栈顶和栈底位置相同
S->stacksize=STACK_INIT_SIZE;
returnOK;
}
StatusDestroyStack(SqStack*S){
if(S->base)
free(S->base);
S->top=S->base=NULL;
returnOK;
}
StatusStackEmpty(SqStackS){
if(S.top==S.base)
returnTRUE;
else
returnFALSE;
}
StatusGetTop(SqStackS,SElemType*e)//从栈中取元素
{
if(S.top==S.base)
returnERROR;
*e=*(S.top-1);
returnOK;
}
StatusPush(SqStack*S,SElemType*e)//在栈顶插入新的元素,入栈
{
if(S->top-S->base>=S->stacksize)
{
S->base=(SElemType*)realloc(S->base,(S->stacksize+STACKINCRENT)*sizeof(SElemType));//重新分配空间
if(!
S->base)
exit(OVERFLOW);
S->top=S->base+S->stacksize;
S->stacksize+=STACKINCRENT;
}
*S->top++=*e;
returnOK;
}
StatusPop(SqStack*S,SElemType*e)
{
if(S->top==S->base)
returnERROR;
*e=*--S->top;
returnOK;
}////////////////////栈模块///////////////////////////////
//队列模块
typedefstructQueue{
QElemType*base;
intfront;//
intrear;//
}SqQueue;
StatusInitQueue(SqQueue*Q);
StatusDestroyQueue(SqQueue*Q);
StatusClearQueue(SqQueue*Q);
StatusQueueEmpty(SqQueueQ);
intQueueLength(SqQueueQ);
StatusGetHead(SqQueueQ,QElemType*e);
StatusEnQueue(SqQueue*Q,QElemType*e);
StatusDeQueue(SqQueue*Q,QElemType*e);
StatusQueueTraverse(SqQueueQ);
StatusInitQueue(SqQueue*Q)//初始化队列
{
Q->base=(QElemType*)malloc(MAXQSIZE*sizeof(QElemType));
if(!
Q->base)
exit(OVERFLOW);
Q->front=Q->rear=0;//
returnOK;
}
StatusDestroyQueue(SqQueue*Q){
if(Q->base)
free(Q->base);
Q->front=Q->rear=0;
returnOK;
}
StatusClearQueue(SqQueue*Q){
if(Q->front==Q->rear)
returnERROR;
else
Q->front=Q->rear=0;
returnOK;
}
StatusQueueEmpty(SqQueueQ){
if(Q.front==Q.rear)
returnTRUE;
else
returnFALSE;
}
StatusEnQueue(SqQueue*Q,QElemType*e)//在队尾插入新的元素,入队
{
if((Q->rear+1)%MAXQSIZE==Q->front)
returnERROR;
Q->base[Q->rear]=*e;
Q->rear=(Q->rear+1)%MAXQSIZE;
returnOK;
}
StatusDeQueue(SqQueue*Q,QElemType*e)
{
if(Q->front==Q->rear)
returnERROR;
*e=Q->base[Q->front];
Q->front=(Q->front+1)%MAXQSIZE;
returnOK;
}/////////////////////////////队列模块/////////////////////////////////
StatusInitBiTree(BiTree*BT);//构造空二叉树
StatusCreateBiTree(BiTree*BT);//建立二叉树
StatusPreOrder(BiTreeBT);//先序遍历
StatusInOrder(BiTreeBT);//中序遍历
StatusPostOrder(BiTreeBT);//后序遍历
StatusLevelOrder(BiTreeBT);//按层次遍历
StatusNRPreOrder(BiTreeBT);//先序非递归遍历二叉树
intmax(intm,intn);
intTreeDepth(BiTreeBT);//求高度
intNodeNumber(BiTreeBT);//求总结点数
voidmain()
{
BiTreeBT;
intflag=1,select;
printf("ToCreateBinaryTree,PleaseInputPreOrderwith'#':
\n");//输入二叉树的先序序列,用#代表空结点
CreateBiTree(&BT);//创建二叉树,返回根结点BT
while(flag){
printf("Pleaseselect:
\n");
printf("1.PreOrderTraversal\n");
printf("2.InOrderTraversal\n");
printf("3.PostOrderTraversal\n");
printf("4.LevelOrderTraversal\n");
printf("5.NRPreOrderTraversal\n");
printf("6.TreeDepth\n");
printf("7.NodeNumber\n");
printf("8.Exit\n");
scanf("%d",&select);
switch(select){
case1:
printf("\nThePreOrderTraversalofBinaryTreeis:
");
PreOrder(BT);//先序遍历
break;
case2:
printf("\nTheInOrderTraversalofBinaryTreeis:
");
InOrder(BT);//中序遍历
break;
case3:
printf("\nThePostOrderTraversalofBinaryTreeis:
");
PostOrder(BT);//后序遍历
break;
case4:
printf("\nTheLevelOrderTraversalofBinaryTreeis:
");
LevelOrder(BT);//按层次遍历
break;
case5:
printf("\nTheNRPreOrderTraversalofBinaryTreeis:
");
NRPreOrder(BT);//先序非递归遍历
break;
case6:
printf("\nTheDepthofBinaryTreeis:
%d",TreeDepth(BT));
break;
case7:
printf("\nTheNumberofNodeis:
%d",NodeNumber(BT));
break;
default:
flag=0;
printf("Pressanykeytoexit!
");
getch();
break;
}
printf("\n");
}
}
/**********************InitBiTree********************/
StatusInitBiTree(BiTree*BT){//构造空二叉树
*BT=NULL;
returnOK;
}
/**********************CreateBiTree********************/
StatusCreateBiTree(BiTree*BT){//建立二叉树
SqStackS;
InitStack(&S);
*BT=NULL;
charch;
intflag;
SElemTypep,e;
scanf("%c",&ch);
while(ch!
='#'){
switch(ch){
case'(':
Push(&S,&p);
flag=1;
break;
case',':
flag=0;
break;
case')':
Pop(&S,&p);
break;
default:
p=(BiNode*)malloc(sizeof(BiNode));
p->lchild=p->rchild=NULL;
p->data=ch;
if(!
(*BT))
*BT=p;
else{
GetTop(S,&e);
if(flag)
e->lchild=p;
else
e->rchild=p;
}
break;
}
scanf("%c",&ch);
}
returnOK;
}
/*********************PreOrder***********************/
StatusPreOrder(BiTreeBT){//先序遍历
if(BT){
if(!
(BT->data))
returnERROR;
printf("%c",BT->data);//访问结点
PreOrder(BT->lchild);//先序遍历左子树
PreOrder(BT->rchild);//先序遍历右子树
returnOK;
}
}
/*******************InOrder*******************/
StatusInOrder(BiTreeBT){//中序遍历
if(BT){
if(!
(BT->data))
returnERROR;
InOrder(BT->lchild);//中序遍历左子树
printf("%c",BT->data);//访问结点
InOrder(BT->rchild);//中序遍历右子树
returnOK;
}
}
/*******************PostOrder*****************/
StatusPostOrder(BiTreeBT){//后序遍历
if(BT){
if(!
(BT->data))
returnERROR;
PostOrder(BT->lchild);//后序遍历左子树
PostOrder(BT->rchild);//后序遍历右子树
printf("%c",BT->data);//访问结点
returnOK;
}
}
/******************LevelOrder*******************/
StatusLevelOrder(BiTreeBT){//按层次遍历
SqQueueQ;
BiTreep;
if(BT){
InitQueue(&Q);
p=BT;
EnQueue(&Q,&p);
while(!
QueueEmpty(Q)){
DeQueue(&Q,&p);
if(!
(p->data))
returnERROR;
printf("%c",p->data);
if((p->lchild))
EnQueue(&Q,&p->lchild);
if((p->rchild))
EnQueue(&Q,&p->rchild);
}
DestroyQueue(&Q);
returnOK;
}
}
/******************NRPreOrder********************/
StatusNRPreOrder(BiTreeBT){//先序非递归遍历二叉树
SqStackS;
BiTreep;
InitStack(&S);
if(BT){
p=BT;
while(p||!
StackEmpty(S)){
while(p){
if(!
(p->data))
returnERROR