1、(5) 在 (4) 基础上,编写程序实现对线索二叉树进行先序、中序和后序遍历的非递归算法,并显示线索二叉树和相应的遍历序列。2、实验环境:带有Codeblocks的电脑 三、设计思想(本程序中的用到的所有数据类型的定义,主程序的流程图及各程序模块之间的调用关系)1、逻辑设计 (1)层次建立算法: 1.输入节点i和数据m不是0和#循环 1.1申请节点q,把节点赋给q的数据域; 1.2将其左右子链置成空; 1.3.1如果i=0,P为根节点 1.3.2否则父节点的编号j为i/2; 1.3.2.1如果i为奇数,为j右儿子 1.3.2.1如果i为偶数,为j左儿子 (2)先序递归建立 1.输入节点的字符
2、1.1如果字符为#,T为空; 1.2否则申请节点T; 1.2.1将字符赋给T的数据域; 1.2.2递归的建立左子树; 1.2.3递归的建立右子树; (3)先序递归遍历 1.如果树T不为空 1.1输出T的数据域 1.2递归的遍历左子树 1.3递归的遍历右子树 (4)中序递归遍历 1.1递归的遍历左子树 1.2输出T的数据域 (5)后序递归遍历 1.3输出T的数据域 (6)先序遍历非递归算法 1.栈s初始化; 2.循环直到root为空且栈s为空 2.1 当root不空时循环 2.1.1 出root-data; 2.1.2 将指针root的值保存到栈中; 2.1.3 继续遍历root的左子树 2.2
3、 如果栈s不空,则 2.2.1 将栈顶元素弹出至root; 2.2.2 准备遍历root的右子树; (7)中序遍历非递归算法 2.1.1 将指针root的值保存到栈中; 2.1.2 继续遍历root的左子树 2.2.2 输出root- 2.2.3 准备遍历root的右子树; (8)后序遍历非递归算法 1. 栈s初始化; 2. 循环直到root为空且栈s为空 2.1 当root非空时循环 2.1.1 将root连同标志flag=1 入栈; 2.1.2 继续遍历root的左子树; 2.2 当栈s 非空且栈顶元素的标志为2 时,出栈并输出栈顶结点; 2.3 若栈非空,将栈顶元素的标志改为2,准备遍历
4、栈顶结点的右子树; (9) 层次遍历算法 1. 队列Q初始化; 2. 如果二叉树非空,将根指针入队; 3. 循环直到队列Q为空 3.1 q=队列Q的队头元素出队; 3.2 访问结点q的数据域; 3.3 若结点q存在左孩子,则将左孩子指针入队; 3.4 若结点q存在右孩子,则将右孩子指针入队; (10)用数组存储广义表递归算法: 1.数组的初始化,和标志的设置i=0; 2. 左括号进数组,i+; 3. 树T的广义表存储 3.1如果T不为空 3.1.1如果左右子树都不为空,则字符进数组,i+; 3.1.2.1否则字符进数组,i+; 3.1.2.2左括号进数组,i+; 3.1.2.3递归遍历左子树
5、3.1.2.4逗号进数组,i+; 3.1.2.5递归遍历右子树 3.1.2.6右括号进数组,i+; 4.右括号进数组,i+ 5用0标记数组结束,i+;2、物理设计 流程图(最左边为主函数,右边为4个子函数及其调用关系):4、测试结果 下面为上图两种建立方式(先序,层次)和六种遍历(先中后根递归和非递归遍历),还有广义表存储和打印的截图:五、系统不足与经验体会1、系统不足 (1)由于时间的关系,没有写线索二叉树及其各种遍历算法和求后继节点的算法; (2)由于空指针总是比节点多一个,造成很大的空间浪费;2、经验体会(1)非递归算法其实就是把递归算法用循环和其他数据结构(本实验中对应的队列和栈)模拟
6、出来,比起非递归算法,递归算法更直观易懂,但是非递归有助于更深入理解该种数据结构;(2)在写非递归算法调试的时候,出现栈陷入死循环,这时候如果设立一个栈的判断空的函数那么就很容易知道看出自己设计算法的问题;(3)很多关于二叉树的算法都是基于遍历二叉树的算法的,比如删除二叉树的算法和求高度的算法;(4)图中的DFS类似于二叉树中的先序遍历算法,这也是为什么在写非递归算法上用栈先进后出这种数据结构实现的原因,他们的共同特点都是尽可能的走远;(5)给定一个先序遍历系列并不能唯一的确定二叉树,比如两个不同方向的斜树; 六、附录:源代码(带注释)#include #includecstdiocstrin
7、g#define maxlen 100using namespace std;struct BTtree char data; BTtree *lchild; BTtree *rchild;char genelist100;/保存广义表int i;BTtree* pre_creat_bt()/先序建立二叉树 char ch; BTtree *T; cin ch; if(ch=#) T=NULL; else T=(BTtree*)malloc(sizeof(BTtree); T-data=ch; / printf(n请输入%c结点的左子结点(如果没有那么输入#代表空):,T-data );lch
8、ild=pre_creat_bt();n请输入%c结点的右子结点(如果没有那么输入#代表空):rchild=pre_creat_bt(); return T;BTtree * level_create()/层次建立二叉链表 BTtree* smaxlen; int j; BTtree *T,*p; while(cin i ch&(i!=0|ch!=) p=(BTtree*)malloc(sizeof(BTtree); p-lchild=NULL;rchild=NULL; si=p; if(i=1)T=p; j=i/2; if(i%2=0)sj-lchild=p;/节点为偶数,i为j的左儿子 e
9、lse sj-rchild=p;void pre_order(BTtree *T)/递归先根遍历二叉树 if(T!=NULL) cout lchild);rchild);void in_order(BTtree *T)/递归中序遍历二叉树 in_order(T-void post_order(BTtree *T)/递归后根遍历二叉树 post_order(T-void npre_order(BTtree *T)/非递归先根遍历二叉树 BTtree* STACKmaxlen; int top=maxlen; while(T!=NULL|top!=maxlen) STACK-top=T; T=T-
10、lchild; if(top! T=STACKtop+;rchild;/*当树非空那么循环,访问,左走若S不空,取栈顶右走*/void nin_order(BTtree *T)/非递归中序遍历二叉树data ; 树不空,左走一步不访问 若栈不空,取出栈顶访问 再访问父亲,再右走void npost_order(BTtree *T)/非递归后根遍历二叉树 struct STACK BTtree* tree; int flag; Smaxlen; BTtree * temp; temp=T; while(temp! if(temp! S-top.tree=temp; Stop.flag=1; te
11、mp=temp- if(Stop.flag=2) T=Stop+.tree; Stop.flag=2; temp=Stop.tree-void lev_order(BTtree* T) BTtree* Qmaxlen,*q=NULL; int front=0,rear=0;/建立一个空的队列 if(T=NULL)return; Qrear+=T;/将根指针入队 while(front!=rear) q=Qfront; q- if(q-lchild! Qrear=q-/左儿子不是空,将它入队列 rear+;rchild!/右边儿子不是空,将它入队列 front+;/完成上面之后将队首元素就可以出
12、队进行下一次循环操作void order(BTtree * T)/遍历二叉链表 printf(*递归遍历二叉链表*n);n先序递归遍历二叉链表: pre_order(T);n中序递归遍历二叉链表: in_order(T);n后序递归遍历二叉链表: post_order(T);n*非递归遍历二叉链表*nn先序非递归遍历二叉链表: npre_order(T);n中序非递归遍历二叉链表: nin_order(T);n后序非递归遍历二叉链表: npost_order(T);n*层次遍历二叉链表*:n lev_order(T);void print_tree(BTtree *T) /*按广义表方式打印*
13、/ if(T-lchild=NULL&T-rchild=NULL) genelisti=T- i+; genelisti=(; print_tree(T-,)void print(BTtree *T) BTtree *t=T; i=0; print_tree(t);0int main() BTtree *pre_t=NULL,*lev_t=NULL; int N;*输入1先序建立二叉链表*n*输入2层次建立二叉链表*n*输入0退出*n N) switch(N) case 1:*先序建立二叉链表*n输入根节点(如果没有那么输入#代表空): pre_t=pre_creat_bt(); order(pre_t);/遍历二叉链表n*二叉树用广义表表示为*: print(pre_t); for(i=0; genelisti! i+) cout genelisti; break; case 2:*层次建立二叉链表*n输入节点次序和元素: lev_t=level_create(); order(lev_t);/遍历二叉链表*/ print(lev_t); i+)cout case 0: break ; default : memset(genelist, ,sizeof(genelist); return 0;/*1A 3C 4D 5E 6F 7G 8H 9I 10J 0#*/
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1