二叉树的后序遍历(迭代法)

 

 迭代法说白了就是用栈模拟了递归解法的过程,先上代码:

# 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: TreeNode) -> List[int]:
        if not root:
            return list()
        
        res = list()
        stack = list()
        prev = None

        while root or stack:
            while root:
                stack.append(root)
                root = root.left
            root = stack.pop()     #1
            if not root.right or root.right == prev:
                res.append(root.val)
                prev = root
                root = None    #2
            else:
                stack.append(root)
                root = root.right   #3
        
        return res

 

到#1为止,可以看到stack将根节点和每个访问的节点的左节点都入栈了,之后将最深最左侧的节点,也就是后序遍历的第一个节点弹出(这个节点已经没有左节点了)。

#2 节点如果没有右节点(就是它是左侧一支)那么就可以把他加到结果里了,同时记录这个点,并将root置空

#3 节点有右节点说明这个是根节点,那么继续将根节点入栈(先进后出嘛),然后root指向那个右节点,第一轮完事。

第二轮:root成为了None  或者 上一次加入栈节点的右节点,None的话就从栈里pop出来一个给它,说明这个是根节点,如果是右节点,先给它入栈(因为马上出栈的也是它只是要先找找它的左侧节点)那么继续找这个节点的左侧节点,没有的话说明这个也是个根节点,和None相同。

 leetcode上大神还有用c++写出了比较好看的后续遍历

class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> result;
        stack<TreeNode*> st;
        if (root != NULL) st.push(root);
        while (!st.empty()) {
            TreeNode* node = st.top();
            if (node != NULL) {
                st.pop();
                st.push(node);                          //
                st.push(NULL);

                if (node->right) st.push(node->right);  //
                if (node->left) st.push(node->left);    //

            } else {
                st.pop();
                node = st.top();
                st.pop();
                result.push_back(node->val);
            }
        }
        return result;
    }
};

作者:carlsun-2

 理解之后,可以轻松的写出前序遍历的代码了,以下是自己写出的前序遍历的代码:

# 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: TreeNode) -> List[int]:
        result = list()
        st = list()
        if root:
            st.append(root)
        while st:
            if len(st):
                node = st.pop(-1)
                if node.right:
                    st.append(node.right)
                if node.left:
                    st.append(node.left)
                result.append(node.val)
        return result
                

  无论是什么遍历,把握好谁先访问谁后入栈的原则。例如这题,根节点一定是前序遍历先访问,那么后入栈或者先出栈。这题很明显:这个节点在它孩子节点入栈前先出栈。所以node每次pop(-1)就是根节点的出栈。

  根节点出栈伴随着 1.右孩子入栈 2.左孩子入栈 ,因为出栈顺序是左孩子先出右孩子后出。

  直至栈空就可

 

posted @ 2021-03-17 09:54  灰人  阅读(588)  评论(0)    收藏  举报