二叉树三种遍历的非递归算法

来源:互联网 发布:2016年开淘宝店怎么样 编辑:程序博客网 时间:2024/05/17 01:34

本人水平有限,以下算法参考了好多资料,整理出了便于记忆的背记版
1。三个算法框架类似,外层while循环条件相同,便于记忆,都以“高歌猛进”作为步骤1;
2。前序中序非常简单,掌握好了“高歌猛进”和“柳暗花明”,一切皆送分;
3。后序关键扩充了栈,分清出入栈时的flag代表的含义,亲自动手遍历一遍,就可知晓;
     网上虽然有后续遍历其他版本,但是判断条件多,格式与前中序不太一致,且需要延迟栈顶
     指针的变动,非常难记;
4。以下仅供参考,但可以肯定的是本人即将考研也是用这套背记版本。

前序遍历背记版
  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
  }

注意几点:
1。外层while判断条件。一般不会有问题
2。内层出栈时的if判断条件,特别容易漏

3。在高歌猛进的时候访问




中序遍历背记版
  StackInit(s);
  p=t;
  while (p!=null || !StackEmpty(s))
  {
    while (p!=null)       //第一步:背记关键词“高歌猛进”遍历左子树
    {
      push(s,p);
      p=p->lchild;   
    }//endwhile
    if (!StackEmpty(s)) //第二步:背记关键词“柳暗花明”,左走不了改走右孩子,通过下一次循环中的内嵌while实现右子树遍历
    {
      p=pop(s);
      visite(p->data);
       p=p->rchild;   
    }//endif
  }

注意几点:
1。外层while判断条件。一般不会有问题
2。内层出栈时的if判断条件,特别容易漏

3。在柳暗花明的时候访问

后序遍历背记版(注意,这个算法我没理解好,尤其是flag那块,后序的还是看我转载的另外一篇文章的吧)
在上述stack结构中增加一个flag标志,标识此节点出栈时是否应该访问
struct stack
{
     TreeType *p;
     int flag;
}
入栈函数Push重载为push(stack s, TreeType *p, int flag);
出栈函数pop  重载为pop(stack s,TreeType *&p, int &flag)(c里改成指针,这里是C++故用引用)
  StackInit(s);
  p=t;

  while (p!=null || !StackEmpty(s))
  {
    while (p!=null)       //第一步:背记关键词“高歌猛进”,一直向左走
    {
       push(s,p,0);       //关键点1:第一次进栈,节点标志位置0
       p=p->lchild;   
    }//endwhile
    pop(s,p,flag);
    while(flag)            //第二步:背记关键词“终成正果”,栈顶左右子树访问完毕
    {
        visite(p->data);
        if (!StackEmpty(s))
           pop(s,p,1);
        else return;
    }
    push(s,p,1);     
    p=p->rchild;        //第三步:背记关键词“左右逢源”,在下一个while中访问p的右子树完毕,
  }
注意几点:
1。外层while判断条件。一般不会有问题
2。入栈时,若flag=0,左子树未访问

     出栈时,若flag=0,左子树未访问
3。入栈时,若flag=1,左子树访问完毕,右子树未访问
     出栈时,若flag=1,左右子树访问完毕。