二叉树的非递归实现【菜鸟学习日记】

这篇是接着上篇的二叉树写的,上篇用递归实现了简单的二叉树,这次用非递归来实现二叉树的前序、中序、后序访问

要非递归实现,我们这里这里借助栈来实现,因为栈的后进先出特性,其实和递归的思想非常相似

这里写图片描述

栈:先入栈的最后出栈,最后入栈的最先出栈

递归:最先调用的最后释放,最后调用的最先释放

这样一比较是不是觉得其实递归的思想其实和栈的特性是一样的

铺垫了那么多进入今天的正题

1、前序
    //非递归实现,借助栈实现
    //递归思想与栈的后进先出特性
    //前序
    void PrevOrder_NonR()
    {
        _PrevOrder_NonR(_root);
    }
    void _PrevOrder_NonR(Node* root)
    {
        Node* cur = root;
        stack<Node*> s;

        while (cur || !s.empty())
        //树还没遍历完
        {
            while (cur)
            {
                cout << cur->_data << " ";
                s.push(cur);
                cur = cur->_left;
            }

            //top从栈取出来,表示左子树已经访问完了,要开始访问右子树了
            Node* top = s.top();
            s.pop();
            cur = top->_right;
        }
    }

这里写图片描述

循环将节点左孩子入栈并打印,当循环结束,代表左子树访问完了,开始右子树的访问

这里写图片描述

访问右子树,并Pop掉此时的top,因为top的作用就是用来找右子树的,这时它就已经完成了它的使命可以退出历史的舞台了,让它的前一个数暴露出来,成为新栈顶,带我们找下一个右子数
2、中序
中序和前序的方法一样,就是再打印数据时不同
//中序
    void InOrder_NonR()
    {
        _InOrder_NonR(_root);
    }
    void _InOrder_NonR(Node* root)
    {
        Node* cur = root;
        stack<Node*> s;
        while (cur || !s.empty())
        {
            while (cur)
            {
                s.push(cur);
                cur = cur->_left;
            }
            //top从栈取出来,表示左子树已经访问完了,要开始访问右子树了
            Node* top = s.top();
            cout << top->_data << " ";
            s.pop();
            cur = top->_right;
        }
    }
3、后序
后序这里跟前面两个有点不太一样,因为后序是左->右->根
所以,我们再访问右子树的时候还不能Pop了根,但是,这样就会死循环,因为访问完右子树,返回到根时,就会又访问右子树,因为我们无法判断刚刚是否访问过右子树了,所以要加个判断条件,创建一个prev指针记录前节点,访问过就不再访问
//后序
    void PostOrder_NonR()
    {
        _PostOrder_NonR(_root);
    }
    void _PostOrder_NonR(Node* root)
    {
        Node* cur = root;
        stack<Node*> s;
        Node* prev = NULL;
        while (cur || !s.empty())
        {
            while (cur)
            {
                s.push(cur);
                cur = cur->_left;
            }

            Node* top = s.top();
        //右子树为空或者右子树刚才访问过了,所以top的prev==top->_left
            if (top->_right == NULL || top->_right == prev)
            {
                cout << top->_data << " ";
                prev = top;
                s.pop();
            }
            //访问右子树
            else
            {
                cur = top->_right;
            }
        }

这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值