第 7 关 | 算法真正开始了 —— 递归与二叉树 : 3.迭代法实现二叉树的遍历-灵析社区

时光小少年

1. 迭代法实现前序遍历

前序遍历是中左右,如果还有左子树就一直向下找。完了之后再返回从最底层逐步向上向右找。 不难写出如下代码: (注意代码中,空节点不入栈)

public List<Integer> preOrderTraversal(TreeNode root) {
    List<Integer> res = new ArrayList<Integer>();
    if (root == null) {
        return res;
    }
    
    Deque<TreeNode> stack = new LinkedList<TreeNode>();
    TreeNode node = root;
    while (!stack.isEmpty() || node != null) {
        while (node != null) {
            res.add(node.val);
            stack.push(node);
            node = node.left;
        }
        node = stack.pop();
        node = node.right;
    }
    return res;
}
class Solution:
    def preorderTraversal(self, root):
        res = list()
        if not root:
            return res

        stack = []
        node = root
        while stack or node:
            while node:
                res.append(node.val)
                stack.append(node)
                node = node.left
            node = stack.pop()
            node = node.right
        return res

此时会发现貌似使用迭代法写出前序遍历并不复杂,我们继续看中序遍历:

2. 迭代法实现中序遍历

再看中序遍历,中序遍历是左中右,先访问的是二叉树左子树的节点,然后一层一层向下访问,直到到达树左面的最底部,再开始处理节点(也就是在把节点的数值放进res列表中)。在使用迭代法写中序遍历,就需要借用指针的遍历来帮助访问节点,栈则用来处理节点上的元素。 看代码:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<>();
        Deque<TreeNode> stack = new LinkedList<TreeNode>();
        while(!stack.isEmpty() || root!= null){
            while(root != null){
                stack.push(root);
                root = root.left;
            }
            root = stack.pop();
            res.add(root.val);
            root = root.right;
        }
        return res;
    }
}
class Solution {
    public:
        vector<int> inorderTraversal(TreeNode* root) {
            vector<int> res;
            stack<TreeNode*> stk;
            while (root != nullptr || !stk.empty()) {
                while (root != nullptr) {
                    stk.push(root);
                    root = root->left;
                }
                root = stk.top();
                stk.pop();
                res.push_back(root->val);
                root = root->right;
            }
            return res;
        }
};
def inorderTraversal(self,root):
    if not root:
        return []

    res = []
    stack = []

    while stack or root:
        while root:
            stack.append(root)
            root = root.left

        node = stack.pop()
        res.append(node.val)
        root = node.right

    return res

3. 迭代法实现后续遍历

后序遍历的非递归实现有三种基本的思路:反转法、访问标记法、和Morris法,可惜三种理解起来都有些难度,如果头发不够,可以等一等再学习。

个人感觉访问标记法是最难理解的方法,而Morris法是一个老外发明的巧妙思想:不使用栈,而是用好树中的null指针,但是实现后序仍然非常麻烦,我们这里不再展开,感兴趣的同学可以查一下,

我们这里只介绍一种好理解又好实现的方法:反转法。

如下图,我们先观察后序遍历的结果是seq={9 5 7 4 3},如果我们将其整体反转的话就是new_seq={3 4 7 5 9}。

你有没有发现要得到new_seq的方法和前序遍历思路几乎一致,只不过是左右反了。前序是先中间,再左边然后右边,而这里是先中间,再后边然后左边。那我们完全可以改造一下前序遍历,得到序列new_seq之后再reverse一下就是想要的结果了,代码如下:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<>();
        if(root == null){
            return res;
        }
        Stack<TreeNode> stack  = new Stack<>();
        TreeNode node = root;
        while(!stack.isEmpty() || node != null){
            while(node != null){
                res.add(node.val);
                stack.push(node);
                node = node.right;
            }
            node = stack.pop();
            node = node.left;
        }
        Collections.reverse(res);
        return res;
    }
}
def postorderTraversal(self, root):
    res = []
    if root is None:
        return res

    stack = []
    node = root

    while stack or node:
        while node:
            res.append(node.val)
            stack.append(node)
            node = node.right

        node = stack.pop()
        node = node.left

    res.reverse()

    return res
public:
vector<int> postorderTraversal(TreeNode* root) {
    vector<int> res;
    if (root == nullptr) {
        return res;
    }

    stack<TreeNode*> stack;
    TreeNode* node = root;

    while (!stack.empty() || node != nullptr) {
        while (node != nullptr) {
            res.push_back(node->val);
            stack.push(node);
            node = node->right;
        }

        node = stack.top();
        stack.pop();
        node = node->left;
    }

    reverse(res.begin(), res.end());

    return res;
}
};


阅读量:676

点赞量:0

收藏量:0