二叉树先序中序后序遍历的非递归实现A

遍历二叉树的递归程序

     可以看到三种遍历方法的递归实现形式完全一样,只需改变visit的位置,就得到不同遍历序列。因此从情感上觉得非递归实现应该形式也完全一样,这是课本给的中序非递归实现:

 

只需将visit(p->data);移动到Push(s,p); 后,就能得到先序遍历的非递归实现。然后在考虑后序遍历时,发现这种形式不适用后序遍历,所以后来不得不自己写了一个后序遍历的非递归程序。然而心里始终觉得不舒服,为什么递归实现上明明如此统一,到了非递归实现后序遍历就与众不同了呢?

 

课本的非递归实现对栈的使用并不和递归栈相同,因此结点的进出栈顺序也和递归栈明显不同,基于这个道理,写了一个完全仿照递归栈工作的非递归实现,关键是出栈的条件发生了变化,而且从直觉上,这个程序的出栈和进栈语句(Push,Pop),赋值左孩子和右孩子(p=p->lchild或rchild)都应只出现一次,如果出现了多次,应该是功能重复了,可以再进行缩减。

程序如下:

 

在这种形式下,只需改变visit的位置就能得到三种遍历的非递归实现,结点的进出栈顺序完全和递归栈一样,判断结点是否出栈的条件是:上一次出栈的结点是栈顶元素的右孩子。

对几棵二叉树进行了试验,结果是对的,但不知道有没有疏忽的地方。

 

                                      来源:http://dimcutter.blog.163.com/blog/static/930932962010437590311/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1.先序遍历非递归算法#define maxsize 100typedef struct{ Bitree Elem[maxsize]; int top;}SqStack;void PreOrderUnrec(Bitree t){ SqStack s; StackInit(s); p=t; while (p!=null || !StackEmpty(s)) { while (p!=null) //遍历左子树 { visite(p->data); push(s,p); p=p->lchild; }//endwhile if (!StackEmpty(s)) //通过下一次循环中的内嵌while实现右子树遍历 { p=pop(s); p=p->rchild; }//endif }//endwhile }//PreOrderUnrec2.中序遍历非递归算法#define maxsize 100typedef struct{ Bitree Elem[maxsize]; int top;}SqStack;void InOrderUnrec(Bitree t){ SqStack s; StackInit(s); p=t; while (p!=null || !StackEmpty(s)) { while (p!=null) //遍历左子树 { push(s,p); p=p->lchild; }//endwhile if (!StackEmpty(s)) { p=pop(s); visite(p->data); //访问根结点 p=p->rchild; //通过下一次循环实现右子树遍历 }//endif }//endwhile}//InOrderUnrec3.后序遍历非递归算法#define maxsize 100typedef enum{L,R} tagtype;typedef struct { Bitree ptr; tagtype tag;}stacknode;typedef struct{ stacknode Elem[maxsize]; int top;}SqStack;void PostOrderUnrec(Bitree t){ SqStack s; stacknode x; StackInit(s); p=t; do { while (p!=null) //遍历左子树 { x.ptr = p; x.tag = L; //标记为左子树 push(s,x); p=p->lchild; } while (!StackEmpty(s) && s.Elem[s.top].tag==R) { x = pop(s); p = x.ptr; visite(p->data); //tag为R,表示右子树访问完毕,故访问根结点 } if (!StackEmpty(s)) { s.Elem[s.top].tag =R; //遍历右子树 p=s.Elem[s.top].ptr->rchild; } }while (!StackEmpty(s));}//PostOrderUnrec
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值