栈的运用表达式的计算文档格式.docx
《栈的运用表达式的计算文档格式.docx》由会员分享,可在线阅读,更多相关《栈的运用表达式的计算文档格式.docx(10页珍藏版)》请在冰豆网上搜索。
掌握二叉树的概念和性质、任意二叉树存储结构和任意二叉树的基本操作,并会求二叉树的高度、二叉树总结点个数、二叉树叶子结点,以及熟练掌握三种遍历,包括前序遍历、中序遍历、后序遍历。
1.2基本要求
在设计程序时,一定要简单明了,程序设计的思想要完善,算法要清晰,能给读者一目了然的感觉。
实现二叉树的建立;
前序、中序和后序遍历;
高度、总结点数、叶子结点数。
2设计功能
2.1数据结构
1.对程序中定义的核心数据结构及对其说明:
typedefstructnode/*二叉树结点类型的定义*/
{intdata;
structnode*lch,*rch;
}btree;
在一个头文件中定义二叉树的链式存储结构。
2.模块的划分及其功能:
本程序主要分为六大模块:
二叉树的建立链式存储结构、前序遍历、中序遍历、后序遍历、求叶子结点个数计算、主函数。
1、二叉树的建立链式存储结构:
主要采用二叉树的性质五,对任意二叉树,先按满二叉树进行编号,由于输入的树并非完全二叉树,所以编号中不一定连续。
算法中使用一个辅助向量s用于存放指向树结点的指针。
如s[i]中存放编号为i的结点的指针,即为该结点的地址。
当结点编号i=1时,所产生的结点为根结点,同时将指向该结点的指针存入s[i]。
当结点编号i>
1时,产生一个新结点之后,也将指向该结点的指针存入s[i],由性质五可知,j=i/2为它的双亲结点编号。
若i为偶数,则它是双亲结点的左孩子,即s[j]->
lch=s[i];
若i为奇数,则它是双亲结点的右孩子,即s[j]->
rch=s[i],将新输入的结点逐一与其双亲结点相连,生成二叉树。
前序遍历DLR:
即访问顺序是根结点左子树子树。
中序遍历LDR:
即访问顺序是左子树根结点右子树。
后序遍历LRD:
即访问顺序是左子树右子树根结点。
求叶子结点个数:
先分别求得左右子树中各叶子结点个数,再计算出两者的和即为二叉树叶子结点数。
主函数:
建立菜单,让各模块分别实现。
2.2各模块之间的调用关系及算法设计
1.二叉树的建立算法实现:
btree*creat()
{btree*s[20],*q,*t;
inti,j,x;
printf("
请输入结点号i和结点数据x=?
(i=0,x=0,exit):
"
);
scanf("
%d%d"
&
i,&
x);
while(i!
=0&
&
x!
=0)
{q=(btree*)malloc(sizeof(btree));
q->
data=x;
lch=null;
rch=null;
s[i]=q;
if(i==1)
t=q;
else
{
j=i/2;
if(i%2==0)
s[j]->
lch=q;
elses[j]->
rch=q;
}
}
returnt;
2.前序遍历:
若二叉树为空,则遍历结束,否则进行如下操作:
(1)访问根结点;
(2)前序遍历根结点的左子树;
(3)前序遍历根结点的右子树。
其算法描述如下:
voidpreorder(btreebt)
{if(bt)
{printf(“%d\t”,bt->
data);
/*访问根结点,这里假设数据域
为整型*/
preorder(bt->
lch);
/*前序遍历左子树*/
rch);
/*前序遍历右子树*/
}
3.中序遍历:
(1)中序遍历左子树;
(2)访问根结点;
(3)中序遍历右子树。
算法描述如下:
voidinorder(bitreebt)
{if(bt)
{inorder(bt->
lchild);
/*中序遍历左子树*/
printf(“%d\t”,bt->
/*访问根结点*/
inorder(btt->
rchild);
/*中序遍历右子树*/
4.后序遍历:
(1)后序遍历左子树;
(2)后序遍历右子树;
(3)访问根结点。
其算法描述如下:
voidpostorder(bitreebt)
{postorder(bt->
/*后序遍历左子树*/
postorder(bt->
/*后序遍历右子树*/
5.求叶子结点个数:
用sum变量表示叶子结点的总个数,用m、n分别表示访问的左右子树中的叶子结点个数。
当树为空时返回0。
当树非空且左右子树存在时,用分别访问出的左右子树中叶子结点的的个数相加。
具体算法描述如下:
intleafs(btree*b)/*求叶子结点数*/
{
intn,m;
if(b==null)return0;
else
if(b->
lch==null&
b->
rch==null)return1;
else
{
n=leafs(b->
lch);
m=leafs(b->
rch);
returnn+m;
6.主函数:
通过在do…..while循环中嵌套switch选择实现菜单,然后在选择菜单项时让各个模块分别实现。
具体算法描述如下:
#include<
stdio.h>
iostream.h>
#include"
lx.h"
voidmain()
btree*t;
inti,j,h,g;
选择后回车,每输入结点数和数据时回车\n"
do
{
printf("
选择1:
建立二叉树\n"
选择2:
先序遍历二叉树\n"
选择3:
中序遍历二叉树\n"
选择4:
后序遍历二叉树\n"
选择5:
求二叉树叶子结点数\n"
请输入选择项:
cin>
>
i;
switch(i)
case1:
t=creat();
break;
case2:
printf("
该二叉树的前序遍历是:
postorder(t);
case3:
该二叉树的中序遍历是:
inor(t);
case4:
该二叉树的后序遍历是:
preorder(t);
case5:
g=leafs(t);
printf("
该二叉树的叶子结点个数g=%d\n"
g);
break;
default:
cout<
<
error"
;
}while(i<
=5);
3功能实现
3.1函数的功能分析
二叉树的周游根据依次输入的结点信息,若输入的结点不是虚结点,则建立一个新结点。
若新结点是第一个结点,则令其为根结点;
否则将新结点作为孩子链接到它的双亲结点上。
如此重复下去,直至输入“00”时为止。
可设置一个指针类型的数组队列,保存已输入结点的地址。
由于是按层次自左至右输入结点的,所以先输入的结点的孩子必定比后输入结点的孩子先进入队列,因此可利用对头指针指向当前必须与其孩子结点必定建立链接的双亲结点,利用队尾指针指向当前的结点,即是当前必须与其双亲建立链接的双亲结点。
若队尾指针为偶数,则表示当前输入的结点编号是偶数,队尾指针所指向的结点应作为左孩子与其双亲链接;
否则队尾指针所指的结点应作为右孩子与其双亲链接。
若双亲结点或孩子结点或孩子结点为虚结点,则无须链接。
若双亲结点与其两个孩子链接完毕,则做出队操作,使队头指针指向下一个等待链接的双亲结点。
3.1函数间的调用关系
4测试
输入:
12233500
选择2输出:
选择3输出:
选择4输出:
现在5输出:
5参考文献
【1】肖宏启.《数据结构(C语言版)》北京:
电子工业出版社2010.
【2】严蔚敏,吴伟民.《数据结构(C语言版)》.北京:
清华大学出版社,2007.
【3】谭浩强.《C程序设计》.北京:
清华大学出版社,2005.
【4】丁峻岭.《C语言程序设计》.北京:
中国铁道出版社,2003.