二叉树的递归和非递归遍历

二叉树的遍历

  • 前序遍历:
    遍历顺序:根节点,左子树,右子树
    递归遍历:访问根节点,递归调用再访问左子树,右子树
//前序遍历
    void PrevOrder()
    {
        _PrevOrder(_root);
        cout << endl;
    }
    void _PrevOrder(Node* root)
    {
        if (root == NULL)
        {
            return;
        }
        cout << root->_data << " ";//根节点
        _PrevOrder(root->_leftNode);//左子树
        _PrevOrder(root->_rightNode);//右子树
    }

非递归遍历:压入根节点的左子树节点并访问,取栈顶元素,对其右子树节点进行压栈(右子树节点作为子树的根节点说不定会有左子树节点)。

这里写图片描述

//前序遍历
    void PrevOrder_NonR()
    {
        Node* cur = _root;
        stack<Node*> s;
        while (cur || !s.empty())
        {
            while (cur)
            {
                cout << cur->_data << " ";
                s.push(cur);
                cur = cur->_leftNode;
            }
            Node* top = s.top();
            cur = top->_rightNode;
            s.pop();
        }
        cout << endl;
    }
  • 中序遍历
    遍历顺序:左子树,根节点,右子树
    递归遍历:递归调用左子树并访问,根节点,再右子树
//中序遍历
    void InOrder()
    {
        _InOrder(_root);
        cout << endl;
    }
    void _InOrder(Node* root)
    {
        if (root == NULL)
        {
            return;
        }
        _InOrder(root->_leftNode);//左子树
        cout << root->_data << " ";//根节点
        _InOrder(root->_rightNode);//右子树
    }

非递归遍历:
和前序遍历一样,建立栈将根节点的左子树节点压入,但不访问。在取栈顶元素的时候对节点进行访问。

//中序遍历
    void InOrder_NonR()
    {
        Node* cur = _root;
        stack<Node*> s;
        while (cur || !s.empty())
        {
            //压入根节点的左子树节点
            while (cur)
            {
                s.push(cur);
                cur = cur->_leftNode;
            }
            //取栈顶元素并进行访问
            Node* top = s.top();
            cout << top->_data << " ";
            s.pop();
            //对右子树节点进行遍历
            cur = top->_rightNode;
        }
        cout << endl;
    }
  • 后序遍历
    遍历顺序:左子树,右子树,根节点
    递归遍历:
//后序遍历
    void PostOrder()
    {
        _PostOrder(_root);
        cout << endl;
    }
    void _PostOrder(Node* root)
    {
        if (root == NULL)
        {
            return;
        }
        _PostOrder(root->_leftNode);//左子树
        _PostOrder(root->_rightNode);//右子树
        cout << root->_data << " ";//根节点
    }

非递归遍历:
左子树节点遍历后不能对直接取栈顶元素进行pop操作,需要对其右子树节点进行判断,这里需要记录上次访问的节点prevNode,右子树节点为空或右子树节点为上次访问过的节点,都说明此子树已经遍历完成。

这里写图片描述

//后序遍历
    void PostOrder_NonR()
    {
        Node* cur = _root;
        Node* prevNode = NULL;//记录上次访问的节点
        stack<Node*> s;
        while (cur || !s.empty())
        {
            while (cur)
            {
                s.push(cur);
                cur = cur->_leftNode;
            }
            Node* top = s.top();
            if (top->_rightNode == NULL || top->_rightNode == prevNode)
            {
                cout << top->_data << " ";
                s.pop();
                prevNode = top;
            }
            else
            {
                cur = top->_rightNode;
            }
        }
        cout << endl;
    }


  • 层序遍历

  1. 利用队列先进先出的特点,将根节点压进队列,如果此根节点存在左子树节点和右子树节点,就将根节点先出队列,再将左子树节点和右子树节点进队列;
  2. 此次进入的左右子树节点也会作为根节点有其对应的左右子树节点,再进行根节点出队列,左右子树节点进队列操作即可,直至所有节点全被遍历。
//层序遍历
    void LevelOrder()
    {
        queue<Node*> q;
        if (_root)
        {
            q.push(_root);
        }
        while (!q.empty())
        {
            Node* front = q.front();
            cout << front->_data << " ";
            q.pop();
            if (front->_leftNode)
            {
                q.push(front->_leftNode);
            }
            if (front->_rightNode)
            {
                q.push(front->_rightNode);
            }
        }
        cout << endl;
    }
  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值