二叉树遍历(前中后层序/非递归)

感谢参考如下
一:前中后序递归实现
/*
前中后序的递归实现理解起来最为简单,要点在于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;
            }
        }
    }
}



  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值