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的特性,至左向右依次将根节点的孩子节点压入队列中

  • 相关阅读:
    Task10 文本预处理
    Task09 批量归一化
    Task06 Basic of CNN
    Task05 梯度消失和梯度爆炸
    Task 04 过拟合,欠拟合及其解决方案
    机器学习 Task 03 多层感知机
    机器学习 task2 softmax与分类模型
    异步与闭包与fetch
    baidu API
    my own JSON
  • 原文地址:https://www.cnblogs.com/energy1010/p/10627827.html
Copyright © 2011-2022 走看看