二叉树的建立及相关算法的实现
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
数据结构实验
实验四
二叉树的建立及相关算法的实现
计算机科学与技术系0901班
组长:
组员:
日期:2011-05-05
2009级 0901班 2011年05月05日
实验类型:综合设计型 实验室:软件实验室三
组长: 组员:
1. 实验题目
二叉树的建立及相关算法的实现
2. 需求分析
本演示程序用VC++编写,实现了以下功能
① 建立一棵二叉树,然后对其进行先序、中序和后序遍历。
② 显示二叉树
③ 求二叉树的高度及二叉树的叶子个数等等
④ 在主函数中设计一个简单的菜单,分别调试上述算法
3. 概要设计
为了实现上述程序功能,需要定义栈的抽象类型如下: ADT Stack{
数据对象:D={i a |i a ∈ElemSet,i=1,2,…,n, n ≧0}
数据对象:R1={<1,-i i a a >|1-i a ,D a i ∈,i=2,…,n}
约定n a 端为栈顶,i a 端为栈底。
基本操作:
InitStack(&S)
操作结果:构造一个空栈S 。
GetTop(S)
初始条件:栈S 已存在。
操作结果:用P 返回S 的栈顶元素。
Push(&S ,ch)
初始条件:栈S 已存在。
操作结果:插入元素ch 为新的栈顶元素。
Pop(&S)
初始条件:栈S 已存在。
操作结果:删除S 的栈顶元素。
}ADT Stack ADT Binary Tree{
数据对象 D :D 是具有相同特性的数据元素的集合。
基本操作 P :
InintBiTree(&T)
操作结果:构造空二叉树T 。
CreateBiTree(&T,definition);
初始条件:definition 给出二叉树T 的定义 操作结果:按definition 构造二叉树T.
Preordertraverse(T,Visit());
初始条件:二叉树T存在,Visit是对节点操作的应用函数。
操作结果:先序遍历T,对每个节点调用函数Visit一次且仅一次。
一旦visit()失败,则操作失败。
Inordertraverse(T,Visit());
初始条件:二叉树T存在,Visit是对节点操作的应用函数。
操作结果:中序序遍历T,对每个节点调用函数Visit一次且仅一次。
一旦visit()失败,则操作失败。
Postordertraverse(T,Visit())
初始条件:二叉树T存在,Visit是对节点操作的应用函数。
操作结果:后序遍历T,对每个节点调用函数Visit一次且仅一次。
一旦visit()失败,则操作失败。
Levelordertraverse(T,Visit())
初始条件:二叉树T存在,Visit是对节点操作的应用函数。
操作结果:层序遍历T,对每个节点调用函数Visit一次且仅一次。
一旦visit()失败,则操作失败。
}ADT BinaryTree
本程序还包含个函数:
(1)计算叶子总数函数:int Sumleaf(BiTree T)
(2)左右子数交换函数:void jiaohuan(BiTree T)
(3)节点数计算函数:int jiedianshu(BiTree T)
(4)深度计算函数:int Depth(BiTree T)
(5)显示二叉树函数:void xianshi(BiTree T)
函数调用图如下:
4.详细设计
#include <stdio.h>
#include<malloc.h>
#include <string.h>
#define maxqsize 100
#define stackincrement 10
typedef struct BiTNode{
char data;
struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
typedef struct{
BiTNode *base;
BiTNode *top;
int stacksize;
}sqstack;
void initstack (sqstack *s) //建栈
{s->base=(BiTNode *)malloc(maxqsize * sizeof(BiTNode));
if(!s->base) printf("存储空间失败!");
else
{s->top=s->base; s->stacksize=maxqsize;}}
void push(sqstack *s,BiTNode e) //压栈
{if(s->top-s->base==s->stacksize)
{s->base=(BiTNode *)realloc(s->base,(s->stacksize+stackincrement) * sizeof(BiTNode));
if(!s->base) printf("存储空间失败"); else
{s->top=s->base+s->stacksize;s->stacksize+=stackincre
*(s->top)=e; s->top++;}
BiTNode pop(sqstack *s) //弹出
{s->top--;return *s->top;}int sety(sqstack *s)
{if(s->top==s->base) return 1; else return 0;}
BiTree Create(BiTree T) //构造二叉链表
{ char ch; ch=getchar(); if(ch=='@') T=NULL; else
{ if(!(T=(BiTNode *)malloc(sizeof(BiTNode)))) printf("Error!");
T->data=ch; T->lchild=Create(T->lchild); T->rchild=Create(T->rchild); }
return T; }
void Preordertraverse(BiTree T) //先序遍历
{ if(T)
{ printf("%c ",T->data); Preorder(T->lchild); Preorder(T->rchild)}
}
void fPreordertraverse(BiTree T) //非递归先序遍历
{sqstack s; BiTree p=T; initstack (&s);
if(p) push(&s,*p);
while(!sety(&s)) {p=(BiTNode *)malloc(sizeof(BiTNode));
*p=pop(&s); printf("%c ",*p); if(p->rchild)
push(&s,*(p->rchild)); if(p->lchild)
push(&s,*(p->lchild));}}
int Sumleaf(BiTree T) //叶子总数
{ int sum=0,m,n; if(T)
{ if((!T->lchild)&&(!T->rchild)) sum++; m=Sumleaf(T->lchild);
sum+=m; n=Sumleaf(T->rchild); sum+=n; } return sum; }
void jiaohuan(BiTree T) //左右子数交换
{BiTree temp;
if(T) {temp=T->lchild; T->lchild=T->rchild;
T->rchild=temp; jiaohuan(T->lchild); jiaohuan(T->rchild);
return -1; }
else return 0;}
void Inordertraverse(BiTree T) //中序遍历
{ if(T)
{ Inordertraverse(T->lchild); printf("%c ",T->data);
Inordertraverse(T->rchild); }}
void fInordertraverse(BiTree T) //非递归中序遍历
{sqstack s; BiTree p=T; initstack (&s);
while(p||!sety(&s)) {while(p)
{push(&s,*p); p=p->lchild;}
if(!sety(&s))
{p=(BiTNode *)malloc(sizeof(BiTNode));
*p=pop(&s); printf("%c ",*p); p=p->rchild;}}}
int jiedianshu(BiTree T) //节点数数目
{if(T==NULL) return 0; else
return(jiedianshu(T->lchild)+jiedianshu(T->rchild)+1);
}
void Postordertraverse(BiTree T) //后序遍历
{ if(T)
{ Postordertraverse(T->lchild);
Postordertraverse(T->rchild); printf("%c ",T->data); } }
void fPostordertraverse(BiTree T) //非递归后序遍历
{sqstack s;
BiTNode p, *l, *r; initstack(&s);push(&s,*T); while(!sety(&s)) { p=pop(&s); l=p.lchild; r=p.rchild;
if (l==NULL && r==NULL)
{printf("%c ", p.data);}
else
{p.lchild = NULL;
p.rchild = NULL;
push(&s, p);
if (r != NULL) push(&s, *r);
if (l != NULL) push(&s, *l)
} }
int Depth(BiTree T) //二叉树深度
{ int dep=0,depl,depr;
if(!T) dep=0;
else
{ depl=Depth(T->lchild);
depr=Depth(T->rchild);
dep=1+(depl>depr?depl:depr);
}
return dep;
}
void xianshi(BiTree T) //显示二叉树
{BiTree stack[100],p;
int leave[100][2],top,n,i,width=4;
if(T!=NULL)
top=1;
stack[top]=T;
leave[top][0]=width;
while(top>0)
{p=stack[top];
n=leave[top][0];
for(i=1;i<=n;i++)
printf(" ");
printf("%c",p->data);
for(i=n+1;i<50;i++)
printf("-");
printf("\n");
top--;
if(p->rchild!=NULL)
{top++;
stack[top]=p->rchild;
leave[top][0]=n+width;
}
if(p->lchild!=NULL)
{top++;
stack[top]=p->lchild;
leave[top][0]=n+width;
}
}
}
void Levelordertraverse(BiTree T) //层序遍历二叉树{int i,j;
BiTree q[100],p;
p=T;
if(p!=NULL)
{i=1;q[i]=p;j=2;
}
while(i!=j)
{p=q[i];
printf("%c ",p->data);
if(p->lchild!=NULL)
{q[j]=p->lchild;
j++;
}
if(p->rchild!=NULL)
{q[j]=p->rchild;
j++;
}
i++;
}
}
void main()
{ BiTree T=NULL;
int sum,dep,sun;
int ch1,ch2,a;
ch1=1;
while(ch1)
{ printf("\n");
printf(" 二叉树子系统 \n"); printf("*************************\n"); printf("* 1--建立一棵二叉树 *\n"); printf("* 2--先序遍历二叉树 *\n"); printf("* 3--中序遍历二叉树 *\n"); printf("* 4--后序遍历二叉树 *\n"); printf("* 5--层序遍历二叉树 *\n"); printf("* 6--二叉树的叶子数 *\n"); printf("* 7--输出二叉树的深度 *\n"); printf("* 8--显示二叉树 *\n"); printf("* 9--非递归先序遍历 *\n"); printf("* 10--非递归中序遍历 *\n"); printf("* 11--非递归后续遍历 *\n"); printf("* 12-- 左右子树交换 *\n");
printf("* 13--二叉树的节点数 *\n");
printf("* 0--返回 *\n");
printf("*************************\n");
printf("提示:“空”用@表示\n");
printf(" 请输入你的选项:");
scanf("%d",&ch2);
printf("\n");
getchar();
switch(ch2)
{case 1:
printf("请输入先序序列:");
T=Create(T);
printf("\n您的树已经建立好!\n\n"); break; case 2:
printf("此二叉树的先序遍历是:");
Preordertraverse(T);
printf("\n");break;
case 3:
printf("此二叉树的中序遍历是:");
Inordertraverse(T);
printf("\n"); break;
case 4:
printf("此二叉树的后续遍历是:");
Postordertraverse(T);
printf("\n"); break;
case 5:
printf("此二叉树的层序遍历是:");
Levelordertraverse(T);
printf("\n");break;
case 6:
printf("此二叉树的叶子树为:");
sum=Sumleaf(T);
printf("%d",sum); break;
case 7:
printf("此二叉树的深度为:");
dep=Depth(T);
printf("\n%d",dep); break;
case 8:
printf("此二叉树的凹回显示如下:\n");
xianshi(T);
printf("\n");break;
case 9:
printf("非递归前序为:");
fPreordertraverse(T);
printf("\n");break;
case 10:
printf("非递归中序为:");
fInordertraverse(T);
printf("\n");break;
case 11:
printf("非递归后序为:");
fPostordertraverse(T);
printf("\n");break;
case 12:
jiaohuan(T);break;
case 13:
printf("此二叉树的节点总数是:");
sun=jiedianshu(T);
printf("%d ",sun);break;
case 0:
ch1=0;break;
}
}
}
5. 调试分析
调试程序时主要的错误是语法的错误,对函数的定义以及调用还不够熟悉。
6. 使用说明
(1)运行程序,界面如下:
(2)输入“1”,先序建立一棵二叉树,界面如下:
(3)输入“2”,先序遍历二叉树,界面如下:
(4)输入“3”,中序遍历二叉树,界面如下:
(5)输入“4”,后序遍历二叉树,界面如下:
(6)输入“5”,层序遍历二叉树,界面如下:
(7)输入“6”,得到二叉树的叶子数,界面如下:
(8)输入“7”,得到二叉树的深度,界面如下:
(9)输入“8”,显示二叉树,界面如下:
(10)输入“9”,非递归先序遍历二叉树,界面如下:
(11)输入“10”,非递归中序遍历二叉树,界面如下:
(12)输入“11”,非递归后序遍历二叉树,界面如下:
(13)输入“12”,左右子树交换,之后显示二叉树。
界面如下:(14)输入“13”,输出二叉树的节点数,界面如下:
(15)输入“0”,返回。
7. 测试结果
运行程序
》输入“1”,先序建立一棵二叉树,输入“ab@@c@@”建立二叉树完成。
》输入“2”,先序遍历二叉树,结果为:abc
》输入“3”,中序遍历二叉树,结果为:bac
》输入“4”,后序遍历二叉树,结果为:bca
》输入“5”,层序遍历二叉树,结果为:abc
》输入“6”,得到二叉树的叶子数,结果为:2
》输入“7”,得到二叉树的深度,结果为:2
》输入“8”,显示二叉树,abc
》输入“9”,非递归先序遍历二叉树,abc
》输入“10”,非递归中序遍历二叉树,bac
》输入“11”,非递归后序遍历二叉树,bca
》输入“12”,左右子树交换,之后显示二叉树,acb
》输入“13”,输出二叉树的节点数,3
8. 实验总结
本程序由小组内的四个成员对各个模块进行编写,之后由我们共同对各个模块进行进行组合调试,期间经过了王春红老师的指导,让我们发现了我们许多的不足之处:
(1) 许多概念性的知识还不够扎实,需要我们继续巩固。
(2) 各模块进行组合时,出现了许多错误,原因是组员之间没有对函数的定义名进行好的沟通,定义名出现了几种不同的写法。
9. 模块分工
王斌:建立二叉树及其各种遍历。
贺永林:二叉树的叶子数,树的深度。
郝云霞:凹回显示二叉树。
汤海平:主函数。