zoukankan      html  css  js  c++  java
  • 二叉树遍历算法

    二叉树遍历算法包含: 前序, 中序, 后序, 层次遍历 共四种算法。

    先序遍历 DLR: 先访问根节点,然后访问左子树, 最后访问右子树

    中序遍历LDR: 先访问左子树,然后根节点,最后访问右子树

    后序遍历LRD: 先访问左子树,然后访问右子树,最后根节点

    层次遍历: 从每层开始,至左向右逐层访问

    先序、中序,后序都可以使用递归方式进行访问,非递归方式使用栈辅助,  层次遍历使用队列作为辅助结构

     

    1. 先序非递归遍历算法:

    每次递归深入的时候,就是将左右孩子节点压栈的过程,在压栈之前,访问该节点;

    每个节点只有在访问完右子树,或者右子树为空时,出栈,为了标志每个节点的右孩子节点是否压栈,可以使用一个标志位flag,将节点的右孩子节点压入栈中,需要改变flag,这样每次访问栈顶元素时,如果判断右子树已访问,直接出栈;

     详细算法如下:

    最开始根节点入栈

    while(栈非空){

    1. 获取栈顶元素cur;

    2. 判断该节点的flag, 如果flag为true,说明该节点右子树已经访问,出栈, 否则 访问该节点cur;

    3. 如果cur有左孩子节点,压入栈中,进入step 1;

    否则,如果有右孩子节点(只有右子树),压入栈中,同时修改cur的标志位flag为true;如果cur为叶子节点,直接出栈,进入step1

    }

    void preOrder(BitNode *t){

    if(!t) return;

    Stack<BitNode*> s;

    s.push(t);

    BitNode *cur=NULL;

    while( !s.empty() ){

    cur= s.top();

    if(cur.flag){

    //右子树已经访问,出栈

    s.pop();

    }else{

    visit(cur); //访问该节点

    if(cur->lchild){

    s.push(cur->lchild);//访问左子树

    }else{

    if(cur->rchild){//访问右子树

    s.push(cur->rchild);

    cur->flag= true;

    }else{

    //叶子节点

    s.pop();

    }

    }

    }

    }

    }

    2. 中序遍历非递归算法:

    与先序遍历类似,只是访问完左子树后访问根节点,访问完根节点,出栈,最后访问完右子树,为了标志每个节点的左子树是否访问,使用标志位flag

     详细算法如下:

    最开始根节点入栈

    while(栈非空){

    1. 获取栈顶元素cur;

    2. 如果cur节点标志位为flag为false, 且该节点有左子树,将左子树压入栈中,同时置该节点标志位flag为true;否则访问该节点,并出栈,如果该节点有右子树,将右孩子压入栈中

    }

    void inOrder(BitNode *t){

      if(!t) return;

          Stack<BitNode*> s;

          s.push(t);

          BitNode* cur=NULL;

          while( !s.empty() ){

        cur = s.top();

                 if(cur->flag){

        visit(cur);

                  s.pop();

                if(cur->rchild){

        s.push(cur->rchild);

        }

      }

       }//while         

    }

    }

    3. 后序遍历二叉树非递归算法:

    先访问左右子树,最后访问根节点,同样的,如果该节点的左右子树都已访问,直接出栈,否则更新节点的访问左右子树状态,如果状态为右子树已经访问,直接出栈

    详细算法如下:

    最开始根节点入栈

    while(栈非空){

    1. 获取栈顶元素cur;

    2. 如果cur节点标志位为flag为2, 右子树已经访问完,访问该节点出栈, 否则,

     如果flag==1, 表明该节点左子树已经访问,开始访问右子树,如果该节点无右子树,访问该节点后直接出栈 否则,将右孩子压入栈中,同时置该节点标志位flag为2

     如果flag==0,表明该节点左右子树均未访问, 先访问左子树,如果该节点有左子树,将左子树压入栈中,同时置该节点标志位flag为1,表明左子树已经访问完, 否则判断如果该节点有右子树,将右孩子压入栈中,同时置该节点标志位flag为2,否则该节点为叶子节点,访问该节点后直接出栈

    }

    void postOrder(BitNode *t){

      if(!t) return;

          Stack<BitNode*> s;

          s.push(t);

          BitNode* cur=NULL;

          while( !s.empty() ){

        cur = s.top();

                 if(cur->flag==2){

        visit(cur);

                  s.pop();

               }else if(cur-> flag==0 ){

             if(cur->lchild){

              s.push(cur->lchild);

             cur->flag =1;

            }else{

          if(cur->rchild){

        s.push(cur->rchild);

                  cur->flag=2;

        }else{

                   //叶子节点

          visit(cur);

                  s.pop();

                }

         }   

      }

       }//while         

    }

    4.层次遍历算法:

    使用队列FIFO的特性,至左向右依次将根节点的孩子节点压入队列中

  • 相关阅读:
    Java实现 蓝桥杯 算法提高 特等奖学金(暴力)
    Java实现 蓝桥杯 算法提高 特等奖学金(暴力)
    Java实现 蓝桥杯 算法提高 GPA(暴力)
    Java实现 蓝桥杯 算法提高 GPA(暴力)
    Java实现 蓝桥杯 算法提高 GPA(暴力)
    Java实现 蓝桥杯 算法提高 套正方形(暴力)
    Java实现 蓝桥杯 算法提高 套正方形(暴力)
    第一届云原生应用大赛火热报名中! helm install “一键安装”应用触手可及!
    云原生时代,2个方案轻松加速百万级镜像
    Knative 基本功能深入剖析:Knative Serving 自动扩缩容 Autoscaler
  • 原文地址:https://www.cnblogs.com/energy1010/p/10627827.html
Copyright © 2011-2022 走看看