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

23 篇文章 0 订阅
15 篇文章 0 订阅

上一篇文章介绍了二叉树的几种遍历方式的递归写法,这篇文章继续介绍他们的迭代写法。没有看过的小伙伴可以戳这个链接

前序遍历

题目链接
  前序遍历意思就是按照“根节点-左子树-右子树”的顺序来遍历二叉树,通过递归方法来实现的话很简单,但要用迭代的话就略显麻烦一点了。我们需要借助一个栈来进行辅助实现迭代的遍历,在遍历时,需要先将右节点放到队列里,再放左节点,因为这样才能让出栈顺序是“根左右”,具体的,对python来说,我们可以用列表来作为栈。

代码\Python

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def preorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        if not root:
            return []
        stack = []
        res = []
        stack.append(root)
        print(stack)
        while len(stack):
            node = stack.pop()
            # 根节点
            res.append(node.val)
            # 右节点入栈
            if node.right:
                stack.append(node.right)
            # 左节点入栈
            if node.left:
                stack.append(node.left)
        
        return res

代码\C++

/**
 * 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) {
        if(!root){
            return {};
        }
        vector<int> res;
        stack<TreeNode*> st;
        TreeNode *node = nullptr;
        st.push(root);
        while(!st.empty()){
            node = st.top();
            st.pop();
            res.push_back(node->val);
            if(node->right){
                st.push(node->right);
            }
            if(node->left){
                st.push(node->left);
            }
        }
        return res;
    }
};

中序遍历

题目链接
  类似的,中序遍历就是遍历的时候把根节点放到中间,即“左子树-根节点-右子树”的顺序。但遍历写法不能轻松修改上面的前序,不能简单的把代码改一下顺序就行。
  具体的,我们需要借助一个指针来帮助遍历,我们需要一直先访问左节点,将碰到的节点先放到栈中,直到没有左节点之后再往回走访问中间节点和右节点。

代码\Python

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        if not root:
            return []
        stack = []
        res = []
        cur = root
        while cur or stack:
            # 中间节点不为空
            if cur:
                stack.append(cur)
                cur = cur.left
            # 没有左节点了,可以往回了
            else:
                # 上一层的中间节点
                cur = stack.pop()
                res.append(cur.val)
                cur = cur.right  # 右节点
    
        return res

代码\C++

if(!root) {
            return {};
        }
        vector<int> res;
        stack<TreeNode*> sk;
        TreeNode *cur = root;
        while(cur || !sk.empty()){
            if(cur){
                sk.push(cur);
                cur = cur->left;
            }
            else{
                cur = sk.top();
                sk.pop();
                res.push_back(cur->val);
                cur = cur->right;
            }
        }
        return res;

后序遍历

添加链接描述
  类似的,后序遍历就是遍历的时候把根节点放到最后,即“左子树-右子树-根节点”的顺序。后序遍历的非递归写法有些麻烦,不过让我们慢慢来,后序的顺序是 左右中,而前序的顺序是中左右,因此我们可以直接在前序遍历的代码上改一下顺序:先让前序遍历变成中右左,再将其逆序,就是左右中。这里python代码就省略了。

代码\C++

/**
 * 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> postorderTraversal(TreeNode* root) {
        if(!root){
            return {};
        }
        vector<int> res;
        stack<TreeNode*> st;
        TreeNode *node = nullptr;
        st.push(root);
        while(!st.empty()){
            node = st.top();
            st.pop();
            res.push_back(node->val);
            // 交换前序遍历中的左右顺序
            if(node->left){
                st.push(node->left);
            }
            if(node->right){
                st.push(node->right);
            }
        }
        // 再反转结果
        reverse(res.begin(), res.end());
        return res;
    }
};

后序遍历-进阶写法

  上一个简单的思路有些取巧,复杂一点的写法需要在遍历过程中记录某个结点是否访问过,具体的,我们可以用一个集合存储访问过的节点。

代码\Python

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def postorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        cur = root
        stack = []
        # 标记遍历过的左右子树
        visited = set()
        res = []
        while cur or stack:
            if cur:
                # 当前中节点入栈,
                stack.append(cur)
                # discard方法及时参数不在里面,也不会报错,remove方法会报错
                visited.discard(cur)
                # 遍历左子树
                cur = cur.left
            else:
                # 取栈顶
                cur = stack[-1]
                if cur not in visited:
                    # 左子树已遍历,右子树还没
                    visited.add(cur)
                    cur = cur.right
                else:
                    # 左右都已遍历完,访问根节点
                    res.append(cur.val)
                    # 出栈
                    stack.pop()
                    # cur 置空,回循环取栈顶继续判断
                    cur = None
        return res

代码\C++

/**
 * 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> postorderTraversal(TreeNode* root) {
        if(!root){
            return {};
        }
        vector<int> res;
        stack<TreeNode*> st;
        set<TreeNode*> visited;
        TreeNode *cur = root;
        while(cur || !st.empty()){
            if(cur){
                st.push(cur);
                // 如果访问过
                if(auto it = visited.find(cur);
                    it != visited.end()){
                    // 就将它置0
                    visited.erase(it);
                }
                cur = cur->left;
            }
            else{
                // 取栈顶
                cur = st.top();
                if(visited.count(cur)){
                    res.push_back(cur->val);
                    st.pop();
                    cur = nullptr;
                }
                else{
                    // 左子树遍历完
                    visited.insert(cur);
                    cur = cur->right;
                }
            }
        }
        return res;
    }
};

层序遍历

题目链接
  层序遍历一般指对二叉树进行从上到下从左到右的一层一层的遍历,同样深度的节点在同一层。迭代的层序遍历需要借助一个队列,类似于广度优先搜索一样。

代码\Python

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:
        if not root:
            return []
        from queue import Queue
        que = Queue()
        que.put(root)
        res = []
        while not que.empty():
            tmp = []
            length = que.qsize()
            for _ in range(length):
                node = que.get()
                tmp.append(node.val)
                if node.left:
                    que.put(node.left)
                if node.right:
                    que.put(node.right)
            res.append(tmp)

        return res

代码\C++

/**
 * 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<vector<int>> levelOrder(TreeNode* root) {
        vector<vector<int>> res;
        if(!root){
            return res;
        }
        queue<TreeNode *> que;
        que.push(root);
        int size = 0, i;
        TreeNode *node = nullptr;
        while(!que.empty()){
            size = que.size();
            vector<int> tmp;
            for(i = 0; i < size; i++){
                node = que.front();
                que.pop();
                tmp.push_back(node->val);
                if(node->left){
                    que.push(node->left);
                }
                if(node->right){
                    que.push(node->right);
                }
            }
            res.push_back(tmp);
        }
        return res;
    }
};

总结

  最常见最基础的4种二叉树的迭代遍历方式,也是二叉树很多题目的基础算法,如果对你有帮助的话,动动手指点个赞吧!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值