二叉树的遍历:迭代实现

Posted You are my ghost

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二叉树的遍历:迭代实现相关的知识,希望对你有一定的参考价值。

二叉树的遍历:迭代实现

二叉树有两种遍历方式:递归实现以及迭代实现,递归实现相信大家已经非常熟悉,今天为大家介绍二叉树的迭代实现以及其代码实现;

迭代遍历的好处

我们都知道,递归调用的函数是存在中“栈”中的,但是栈的容量并不大;在进行递归实现时,如果构造的二叉树过大,容易栈溢出;

但是在使用迭代实现时,是将所遍历的节点存在已经开好的空间中,这个空间开在“堆”上,堆的容量可以认为是无限大的,便不存在溢出的问题。
在这里插入图片描述

迭代遍历代码实现

前序遍历

前序遍历:根节点->左孩子->右孩子;
思路:定义一个当前节点cur=root,从cur开始一直向左孩子走,每遍历一个节点,若cur不为空,便将cur节点指针存入栈中,将cur节点数据存入vector数组中,直到左孩子为空;这时cur为栈顶,也为该支链最后一个左孩子,然后去访问cur的右孩子(cur=top->right),再将栈顶pop(出栈),依然边入栈边入vector数组;遍历完该支链后会回到上一层,遍历上层节点的左支链;以此类推。

以上述二叉树为例,前序遍历的结果为{5,3,1,0,2,4,7,6,8,9},

在这里插入图片描述

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution 
{
public:
    vector<int> preorderTraversal(TreeNode* root) 
    {
        vector<int>v;
        stack<TreeNode*>st;
        TreeNode*cur=root;
        while(cur||!st.empty())
        {
            while(cur)
            {
                st.push(cur);
                v.push_back(cur->val);
                cur=cur->left;
            }
            TreeNode* top=st.top();
            cur=top->right;
            st.pop();
        }
        return v;
    }
};

中序遍历

中序遍历的思路与前序遍历相同,唯一不同的操作时是在访问到最后一个左孩子之后再在vector数组中插入数据;

中序遍历:左孩子->根节点->右孩子;
思路:定义一个当前节点cur=root,从cur开始一直向左孩子走,每遍历一个节点,若cur不为空,便将cur节点指针存入栈中,直到左孩子为空;这时cur为栈顶,也为该支链最后一个左孩子,将cur节点数据存入vector数组中,然后去访问cur的右孩子(cur=top->right),再将栈顶pop(出栈),依然访问到最后一个左孩子后边在vector数组入数据边出栈;遍历完该支链后会回到上一层,遍历上层节点的右支链;以此类推。

以上述二叉树为例,中序遍历的结果为{0,1,2,3,4,5,6,7,8,9},
在这里插入图片描述

class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) 
    {
        vector<int>v;
        stack<TreeNode*>st;
        TreeNode*cur=root;
        while(cur||!st.empty())
        {
            while(cur)
            {
                st.push(cur);
                cur=cur->left;
            }
            TreeNode*top=st.top();
            v.push_back(top->val);
            cur=top->right;
            st.pop();
        }
        return v;
    }
};

后序遍历

后序遍历的难度略有提升,在后续遍历时,需要避免父亲节点的二次访问;

思路:定义一个当前节点cur=root,已访问节点的父亲节点prev=nullptr,从cur开始一直向左孩子走,每遍历一个节点,若cur不为空,便将cur节点指针存入栈中,直到左孩子为空;这时定义top=cur为栈顶,也为该支链最后一个左孩子,如果top->right不为空且不为prev,则将top节点数据存入vector数组中,然后出栈,这时top为上一个已访问节点的父亲节点,所以令prev=top便可以去继续访问上一层的右子树,如果top->right不为空或未访问,便访问top的右树;以此类推。

以上述二叉树为例,中序遍历的结果为{0,2,1,4,3,6,9,8,7,5},
在这里插入图片描述

class Solution 
{
public:
    vector<int> postorderTraversal(TreeNode* root) 
    {
        vector<int>v;
        stack<TreeNode*>st;
        TreeNode*cur=root;
        //prev存已访问节点的父亲节点
        TreeNode*prev=nullptr;
        while(cur||!st.empty())
        {
            //保存左路节点路线
            while(cur)
            {
                st.push(cur);
                cur=cur->left;
            }
            TreeNode*top=st.top();
            //如果此时top的左孩子为空或者已经访问,说明右树已经访问完了或无右树,
            //便将数据存入vector数组并出栈;访问根节点并返回上一层,继续访问上一层的右树。
            if(top->right==nullptr||top->right==prev)
            {
                v.push_back(top->val);
                st.pop();
                prev=top;
                cur=nullptr;
            }
            //top->right不为空或未访问,便访问top的右树
            else
            {
                cur=top->right;
            }
        }
        return v;
    }
};

以上是关于二叉树的遍历:迭代实现的主要内容,如果未能解决你的问题,请参考以下文章

二叉树的遍历:迭代实现

一个套路,写出来二叉树的迭代遍历

二叉树的递归与迭代遍历

最全二叉树的遍历方式总结

最全二叉树的遍历方式总结

二叉树的前序中序后序遍历迭代实现