zoukankan      html  css  js  c++  java
  • 实现遍历二叉树遍历(前中后层序/非递归)

    最近使用开发的过程中出现了一个小问题,顺便记录一下原因和方法--实现遍历

        

    感激考参如下

        

        

        

    一:前中后序递归实现
    /*
    前中后序的递归实现懂得起来最为单简,要点在于visit(node)的位置。
    */
    /*
    前中后序递归实现
    */
    //序前历遍
    void BT_PreOrder(BitTree node)
    {
        if(!node) return;
    
        visit(node);
        BT_PreOrder(node->left);
        BT_PreOrder(node->right);
    }
    
    //中序历遍
    void BT_InOrder(BitTree node)
    {
        if(!node) return;
    
        BT_PreOrder(node->left);
        visit(node);
        BT_PreOrder(node->right);
    }
    
    //中序历遍
    void BT_PostOrder(BitTree node)
    {
        if(!node) return;
    
        BT_PreOrder(node->left);
        BT_PreOrder(node->right);
        visit(node);
    }

        


    二:层序递归实现
    /*
    层序历遍
    这类式方用队列来实现,也是最易容懂得的式方,路思如下:
    按照层序历遍的定义,问访完以后节点之后,则以后节点的左子节点具有了倒数第二优先级,以后节点的右子节点具有了倒数第一优先级,用利队列先进先出的特性(可以肯定最低的优先级),可以实现。
    */
    void BT_LevelOrder(BitTree node)
    {
        if(!node) return;
    
        queue<BitTree> q;
        q.push(node);
    
        BitTree pvNode;
        while(!q.empty())
        {
            pvNode = q.pop();
            visit(pvNode);
    
            if(!pvNode->left) q.push(pvNode->left);
            if(!pvNode->right) q.push(pvNode->right);
        }
    }



        


        

    三:序前非递归实现
    /*
    序前历遍非递归实现1
    这类式方用栈来实现,也是最易容懂得的式方,路思如下:
    按照序前历遍的定义,问访完以后节点之后,则以后节点的左子节点具有了第一优先级,以后节点的右子节点具有了第二优先级,
    用利栈后进先出的特性(可以肯定最高的优先级),可以实现。
    */
    void BT_PreOrderNoRec(BitTree node)
    {
        if(!node) return;
    
        stack<BitTree> s;
        BitTree pvNode;
        s.push(node);
        while(!s.empty())
        {
            pvNode = s.pop();
            visit(pvNode);
    
            if(!pvNode->right) s.push(pvNode->right);
            if(!pvNode->left)  s.push(pvNode->left);
        }
    }
    
    /*
    序前历遍非递归实现2
    在网上看到的一种写法,个人认为不如第一种实现起来更易懂
    */
    void BT_PreOrderNoRec2(BitTree node)
    {
        if(!node) return;
    
        stack<BitTree> s;
        while(!node && !s.empty())
        {
            /*如果以后节点不为空,则直接问访,然后将节点存储到栈中(仅仅用来未来找寻右子节点),然后以后节点变成左字节点*/
            if(node)
            {
                visit(node);
                s.push(node);
                node = node->left;
            }
            /*如果以后节点为空,则到栈中出取上一个节点,并找出右子节点行进问访*/
            else
            {
                node = s.pop();
                node = s.right;
            }
        }
    }
        每日一道理
    生命,是一场漫长的棋局。这盘棋没有猎猎西风,没有四起狼烟,只有在取舍和进退中抉择。只有像棋中的小卒那样,勇往直前,毫不退缩沿着沟沟坎坎的人生之路,艰难而执着的求索,前进,才会谱写人生最壮丽的强者之歌。

    四:中序非递归

    /*
    中序历遍非递归实现
    用栈来实现,这类式方可以用递归的路思来懂得
    */
    void BT_InOrderNoRec(BitTree node)
    {
        if(!node) return;
    
        stack<BitTree> s;
        while(!s.empty())
        {
            /*如果以后节点不为空,则不问访,而是将它放入栈中,然后以后节点变成左字节点;
              直一取采这类式方,根据栈先进后出的点特,未来问访的时候左字节点在前,以后节点在后;
              正好是中序历遍的特性
            */
            if(!node)
            {
                push(node);
                node = node->left();
            }
            /*如果以后节点为空,则去栈里出取节点问访,然后问访右子节点。
              这里有些好不懂得,其实这里的开始是左字节点为空了,所以问访了以后节点,然后右子节点;
              同时以后节点为根的二叉树实际上是层上的左字节点,次依类推正好是中序历遍的特性
            */
            else
            {
                node = s.pop();
                visit(node);
                node = node->right;
            }
        }
    }



    五:后序非递归

    /*
    后序历遍非递归实现
    用栈来实现,不是很好懂得,但是最少不必借助各种标记位
    路思如注释所写
    */
    void BT_PostOrderNoRec(BitTree node)
    {
        if(!node) return;
    
        stack<BitTree> s;
        BitTree tmp;//用来标记刚刚问访过的节点
        while(!node && !s.empty())
        {
            //如果以后节点不为空,则压入栈,以后节点变成左字节点
            if(node)
            {
                s.push(node);
                node = node->left;
            }
            //如果为空,则需要根据栈顶的节点来定判下一步
            else
            {
                //获得栈顶节点,不是pop
                node = s.getPop();
                //如果栈顶节点有右子节点,并且(这好不懂得,但很要重)右子节点不是我们刚刚问访过的,
                //则,我们要去右子树问访
                if(node->right && node->right != tmp)
                {
                    //把右子树看成一个新的开始行进问访:根节点压入栈,问访左字节点
                    s.push(node->right);
                    node = node->right->left;
                }
                //如果栈顶节点没有右子节点,或者我们刚刚问访过右子节点,则到达后序历遍的求要,我们可以问访以后节点
                else
                {
                    //问访以后节点,设置标记节点(tmp)为以后节点,以后节点置为空
                    node = s.pop();
                    visit(node);
                    tmp = node;
                    node = null;
                }
            }
        }
    }


    文章结束给大家分享下程序员的一些笑话语录: 问路
    有一个驾驶热气球的人发现他迷路了。他降低了飞行的高度,并认出了地面 上的一个人。他继续下降高度并对着那个人大叫,“打扰一下,你能告诉我我 在哪吗?”
    下面那个人说:“是的。你在热气球里啊,盘旋在 30 英尺的空中”。
    热气球上的人说:“你一定是在 IT 部门做技术工作”。
    “没错”,地面上的人说到,“你是怎么知道的?”
    “呵呵”,热气球上的人说,“你告诉我的每件事在技术上都是对的,但对都没 有用”。
    地面上的人说,“你一定是管理层的人”。
    “没错”,热气球上的人说,“可是你是怎么知道的?”
    “呵呵”,地面上的那人说到,“你不知道你在哪里,你也不知道你要去哪,你 总希望我能帮你。你现在和我们刚见面时还在原来那个地方,但现在却是我 错了”。

  • 相关阅读:
    UINavigationBar 调整
    UILabel根据内容自动调整高度
    [iOS开发]文档导读
    [iOS开发]NSUserDefaults使用注意
    Xcode 断点的使用
    [iOS开发] UIKit Dynamics
    [iOS开发]ShareSDK
    objective-c GCD
    面向对象设计原则
    Go语言学习教程:go语言的包管理
  • 原文地址:https://www.cnblogs.com/xinyuyuanm/p/3065354.html
Copyright © 2011-2022 走看看