二叉树后序线索化.docx
- 文档编号:30728419
- 上传时间:2023-08-19
- 格式:DOCX
- 页数:14
- 大小:470.63KB
二叉树后序线索化.docx
《二叉树后序线索化.docx》由会员分享,可在线阅读,更多相关《二叉树后序线索化.docx(14页珍藏版)》请在冰豆网上搜索。
二叉树后序线索化
二叉树后序线索化
一、功能概述
本系统所实现的功能是采用二叉链表存储二叉树,并按后序遍历对二叉树进行线索化处理。
本系统的二叉树构造简单,无需知道其先序序列、中序序列或者后序序列,任何一个二叉树的构造可由用户跟根系统提示输入二叉的各个结点,构造完二叉树后可对二叉树进行后序线索化,并输出该二叉树的后序序列。
进入本系统主菜单,一是建立一个二叉树,二是对二叉树进行后序线索化,在构建二叉树时,系统提示先创建二叉树根跟结点,然后进入系统构建二叉树的子菜单,该菜单会依次提示用户创建各个结点的左孩子和右孩子,二叉树建立完成后自动返回主采单,用户可选择对该二叉树进后序线索化。
二、总体设计
1、设计思路
为了得到一个棵线索二叉树,可以利用某结点空的左指针域指出该结点在某种遍历序中的直接前驱结点的位置,利用结点空的右指针域指出该结点在某种遍历序列中的直接后继结点的位置,对于那些非空的指针域扔然存放指向该结点左、右孩子的指针。
在得到一棵线索二叉树之前,我们必需先建立一个二叉树,为了使系统使用的更方便更简易,我定义一个构造二叉树的函数,和几个生成左孩子和右孩子的函数,在构造二叉树的函数中,根据用户需要,判断用户输入的要求,不断调用左孩子或右孩子函数,从而完成二叉树的建立。
比如,用户要在X结点中生成一个左孩子,则先判断X的左孩子是否为空,不为空则提示左孩子已建立,请重新输入,并返回上层菜单;若为空,则申请一个新的结点空间,并将X的左孩子指针指向新生成的结点。
建立好一棵二叉树后,对其进行线索化处理,以后序遍历为例,在遍历的过程中,依次判断某结点的左孩子或右孩子是否为空,若不为空,则将其标志域lbit或rbit置为1。
2、设计框架图
3、设计流程图
三、详细设计
1、主函数
(1)功能描述:
构造系统的主菜单界面,有两个选项,一是建立一个二叉树,二是对二叉树进行后序线索化,并用一些编程工具能支持的字符美化主界面。
(2)实现过程:
通过printf语句来实现美化整个主界面输出的效果,和主菜单的各个选项,用switch语句来实现主菜单的选择事件的发生。
(3)程序代码:
voidmain()
{
inta,j;
BTREEbt;
bt=null;
start:
printf("---------------------------------------------------------\n");
printf("\n┃★★★★★★★★★★★★★┃");
printf("\n┃【1】.建立一棵二叉树┃");
printf("\n┃【2】.二叉树后序线索化┃");
printf("\n┃MadeBy:
08321224饶立平┃");
printf("\n┃★★★★★★★★★★★★★┃\n");
printf("---------------------------------------------------------\n");
printf("请选择:
");
scanf("%d",&j);
switch(j)
{
case1:
{
printf("***********************\n");
printf("┃输入二叉树的根结点:
┃\n");
printf("***********************\n");
printf("请输入结点:
");
scanf("%d",&a);
bt=BThead(a,null,null);/*建立二叉树根结点*/
bttree(bt);/*建立二叉树的各个结点*/
gotostart;/*返回主菜单*/
}
case2:
{
if(bt==null)
{
printf("**************************************\n");
printf("二叉树不存在,请重新建立二叉树。
\n");
printf("**************************************\n");
}
else
{
printf("〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓\n");
printf("*****二叉树后序序列如下*****\n");
printf("**********\n");
POSTREAD(bt);/*后序线索化二叉树*/
printf("\n〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓\n");
}
gotostart;/*返回主菜单*/
}
}
}
2、建立一棵二叉树各结点
(1)功能描述:
根据用户自己的输入,首先建立二叉树的根结点,然后根据二叉树的构造,用户自己可随意输入各个结点的左孩子和右孩子,直至整个二叉树构建完成。
(2)算法描述:
通过自定义的BTREEBThead函数来建立用户输入的根结点,之后用一个堆栈STACK[top]来储存结点,和一个while(top>-1)循环来实现用户对各个结点的建立,每建立一个结点储存在STACK[top]中,top+1;若要返回上一结点,则只需top-1,进行出栈操作便可。
这样,便实现了随意构造某结点的左孩子和右孩子,从而使得用户创建二叉树而不受限制。
(3)程序代码:
voidbttree(BTREEbt)
{
intk,top=-1;
intb,c=0;
STACK[++top]=bt;/*头结点进栈*/
while(top>-1)
{
q=STACK[top];/*把栈顶结点元素赋值给q*/
b=q->data;
printf("****************************************************\n");
printf("┃☆╭┐┌╮☆°.·┃\n");
printf("┃╭┘└┘└╮∴°☆°1.添加结点(%d)的左孩子。
┃\n",b);
printf("┃└┐..┌┘—╮∴°2.添加结点(%d)的右孩子。
┃\n",b);
printf("┃╭┴——┤├╮3.返回上一个结点。
┃\n");
printf("┃│o o│ │●°4.二叉树已经建立完成。
┃\n");
printf("┃╰┬——╯ │∴°·┃\n");
printf("┃☆9-|-9--/∴☆.☆╭┐┌╮☆°┃\n");
printf("****************************************************\n");printf("请选择:
");
scanf("%d",&k);
switch(k)
{
case1:
{
if(q->lchild!
=null)
{
printf("********************************************\n");
printf("结点(%d)已经有了左孩子,请重新选择。
\n",b);
printf("********************************************\n");
}
else
{
printf("***************************\n");
printf("┃输入结点(%d)的左孩子结点:
┃\n",b);
printf("请输入:
");
scanf("%d",&c);
T=BTlchild(q,c);/*建立左孩子结点T*/
STACK[++top]=T;/*左孩子结点进栈*/
}
}break;
case2:
{
if(q->rchild!
=null)
{
printf("********************************************\n");
printf("结点(%d)已经有了右孩子,请重新选择。
\n",b);
printf("********************************************\n");
}
else
{
printf("***************************\n");
printf("┃输入结点(%d)的右孩子结点:
┃\n",b);
printf("请输入:
");
scanf("%d",&c);
T=BTrchild(q,c);/*建立右孩子结点T*/
STACK[++top]=T;/*右孩子结点进栈*/
}
}break;
case3:
q=STACK[top--];break;/*最后一个结点出栈*/
case4:
top=-1;break;/*清空堆栈*/
}
}
printf("-------------------------------------------\n");
printf("二叉树已经建立完成,如下所示:
\n");
printf("****************************\n");
printf("*****number\tdata*****\n");
outbtree(bt);/*输出二叉树的结点*/
}
3、对二叉树进行后序线索化
(1)功能描述:
用户建立好一个完整的二叉树后,为了使二叉树的遍历操作提供了更多的方便,而且不需要设置堆栈,将左右孩子不为空的标志域lbit或rbit置为1。
(2)算法描述:
通过利用二叉树的二叉链表结构中的那些空的指针域,来指出二叉树中每个结点在这个序列中的直接前驱结点和直接后继结点是什么,用递归构造一个后序遍历方式实现线索化的函数,依次判断某结点的左孩子或右孩子是否为空,若不为空,则将其标志域lbit或rbit置为1。
(3)程序代码:
BTREEpost;
voidPOSTREAD(BTREET)
{
if(T)
{
POSTREAD(T->lchild);/*递归线索左子树*/
POSTREAD(T->rchild);/*递归线索右子树*/
if(!
T->lchild)
{
T->lbit=1;/*T的标志域置为1*/
T->lchild=post;
}
if(!
T->rchild)
T->rbit=1;/*T的标志域置为1*/
if(post&&post->rbit==1)
post->rchild=T;
post=T;
printf("%d",T->data);/*输出访问的结点*/
}
}
四、效果及存在问题
1、主菜单界面
如图4-1.1所示,以构造一棵图示的二叉树为例,建立二叉树后输出该二叉树的各个结点,对其进行后序线索化,并以后序序列的形式输出。
图:
4-1.1
2、创建根结点
3、创建各个结点左右孩子
图4-3.1,建立根结点1的左孩子结点2.
图4-3.2,建立结点2的右孩子结点5.
图4-3.3,返回结点5的上一个结点2.
根据系统提示可分别建立各个结点的左右孩子结点,直至一棵二叉树建立完成。
由于该二叉树的结数比较多,在此不一一列出各结点的建立过程。
4、输出二叉树各结点
5、对二叉树后序线索化
6、存在的问题
本系统虽然可以成功运行,也能实现课题要求的各个功能,但是因为时间原因部分细节问题还没有有效的解决。
一是在输出二叉树各个结点的时候,编号没有递增显示;二是我一直在构造一个在输出二叉数的各个结点时可以显示各结点的左右孩子结点的数据,我分别用了一个q->lchild->data和q->rchild->data来显示孩子结点存放的数据,但是当某结点左右孩子为空时,则系统会出错,在这个问题上浪费了较多的时间,只好舍去了。
五、心得
通过本次《数据结构》课程设计使我对二叉树后序线索化的原理有了较为清楚的理解,可以解释原来不懂的程序,对于各种函数的调用也有了很好的掌握,对C语言程序设计也有了一定的提高。
在拿到这个课题之前老师就交待过不能抄袭网上的程序,于是,在接到二叉树线索化这个课题后我便将书上二叉那张从头又看了一遍,第一个闪过的念头就是我想做一个可以由用户自己根据二叉树的构造随意建立个各个结点,直至整个二叉树构造完成。
也就是说,可以不用根据该二叉树的前、中、后序序列来构造二叉树,只需用户根据系统提示,依次建立各个结点的左右孩子便可。
在程序设计中,也碰到了很多的问题,有时候运行时不免会遇到很多语法错误,最终都算是一一调试成功,我是在c++的环境下用c语言来进行编程,在c++和c中都能正常运行,只是因为c不技持中文和部分字符的显示。
以致程序运行时会出现乱码。
可以说,在本次《数据结构》课程设计中我是受益非浅啊,看着自己做好的程序不由自喜一把,对于c语言的运用和VC的编程软件掌握更上了一个台阶,我会继续加油努力的!
六、参考文献
数据结构教程(第二版)唐发根编著
北京航空航天大学出版社
C语言程序设计夏涛编著
北京邮电大学出版社
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 二叉 树后序 线索