二叉樹的先,中,后序遍歷(遞歸,非遞歸)


二叉樹的先,中,后序遍歷(遞歸,非遞歸)

作者:Grey

原文地址:

博客園:二叉樹的先,中,后序遍歷(遞歸,非遞歸)

CSDN:二叉樹的先,中,后序遍歷(遞歸,非遞歸)

說明

本文主要介紹了二叉樹的先序,中序,后序遍歷。並且分別用如下兩種方式實現:

  1. 遞歸方法
  2. 非遞歸(使用棧)

示例二叉樹

image

數據結構

public static 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;
    }
}

先序遍歷

先序遍歷流程

先頭,再左,再右。

示例中的二叉樹,先序遍歷的結果為:

1-->2-->4-->7-->11-->8-->12-->3-->5-->6-->9-->13-->10

遞歸方法實現先序遍歷

class Solution {
  public List<Integer> preorderTraversal(TreeNode root) {
        if (root == null) {
            return new ArrayList<>();
        }
        List<Integer> ans = new ArrayList<>();
        pre(root, ans);
        return ans;
    }

    private void pre(TreeNode root, List<Integer> ans) {
        if (root == null) {
            return;
        }
        ans.add(root.val);
        pre(root.left, ans);
        pre(root.right, ans);
    }
}

使用棧實現先序遍歷

整個流程是分如下幾個步驟:

第一步,申請一個棧,並把頭節點壓入。

第二步,彈出就收集答案。

第三步,第二步中彈出的節點,如果右孩子不為空,則右孩子入棧。

第四步,第二步中彈出的節點,如果左孩子不為空,則左孩子入棧。

第五步,循環執行第二步到第四步,直到棧為空。

class Solution {
  public List<Integer> preorderTraversal(TreeNode root) {
        if (null == root) {
            return new ArrayList<>();
        }
        List<Integer> ans = new ArrayList<>();
        Deque<TreeNode> stack = new ArrayDeque<>();
        stack.push(root);
        while (!stack.isEmpty()) {
            TreeNode node = stack.pop();
            ans.add(node.val);
            if (node.right != null) {
                stack.push(node.right);
            }
            if (node.left != null) {
                stack.push(node.left);
            }
        }
        return ans;
    }
}

測評鏈接:LeetCode 144. Binary Tree Preorder Traversal

中序遍歷

中序遍歷流程

先中,再左,再右。

示例中的二叉樹,中序遍歷的結果為:

2-->11-->7-->4-->12-->8-->1-->5-->3-->9-->13-->6-->10

遞歸方法實現中序遍歷

class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        if (root == null) {
            return new ArrayList<>();
        }
        List<Integer> ans = new ArrayList<>();
        in(root, ans);
        return ans;
    }

    private void in(TreeNode root, List<Integer> ans) {
        if (root == null) {
            return;
        }
        in(root.left, ans);
        ans.add(root.val);
        in(root.right, ans);
    }
}

使用棧實現中序遍歷

也是申請一個棧,有如下幾個步驟:

第一步,整條左邊界入棧。

第二步,彈出就收集答案。

第三步,來到右樹上執行同第一步的操作。

第四步,直到棧為空。

class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        if (root == null) {
            return new ArrayList<>();
        }
        List<Integer> ans = new ArrayList<>();
        Deque<TreeNode> stack = new ArrayDeque<>();
        TreeNode cur = root;
        while (!stack.isEmpty() || cur != null) {
            if (cur != null) {
                // 整條左邊界入棧
                stack.push(cur);
                cur = cur.left;
            } else {
                TreeNode node = stack.pop();
                // 彈出收集答案
                ans.add(node.val);
                // 來到右樹上做同樣的操作
                cur = node.right;
            }
        }
        return ans;
    }
}

測評鏈接:LeetCode 94. Binary Tree Inorder Traversal

后序遍歷

后序遍歷流程

先左,后右,再中。

示例中的二叉樹,后序遍歷的結果為:

11-->7-->12-->8-->4-->2-->5-->13-->9-->10-->6-->3-->1

遞歸方法實現后序遍歷

class Solution {
    public List<Integer> postorderTraversal(TreeNode root) {
        if (root == null) {
            return new ArrayList<>();
        }
        List<Integer> ans = new ArrayList<>();
        post(root, ans);
        return ans;
    }

    public void post(TreeNode root, List<Integer> ans) {
        if (root == null) {
            return;
        }
        post(root.left, ans);
        post(root.right, ans);
        ans.add(root.val);
    }
}

使用兩個棧實現后序遍歷

由於我們已經可以通過棧來實現先序遍歷,即:先頭,再左,再右。

而后序遍歷的流程是:先左,再右,再頭。

所以我們可以通過先序遍歷的代碼簡單加工得到后序遍歷的代碼。

首先,我們先通過先序遍歷的代碼,將先序遍歷加工成:先頭,再右,再左。

把這個結果放入一個棧中,假設這個棧叫helper, 然后將helper中的內容依次彈出,便是后序遍歷的結果。

class Solution {
    public List<Integer> postorderTraversal(TreeNode root) {
        if (root == null) {
            return new ArrayList<>();
        }
        List<Integer> ans = new ArrayList<>();
        Deque<TreeNode> helper = new ArrayDeque<>();
        Deque<TreeNode> stack = new ArrayDeque<>();
        TreeNode cur = root;
        stack.push(cur);
        while (!stack.isEmpty()) {
            TreeNode node = stack.pop();
            helper.push(node);
            // 先序遍歷的時候,是先判斷右樹,改造一下,先判斷左樹
            if (node.left != null) {
                cur = node.left;
                stack.push(cur);
            }
            if (node.right != null) {
                cur = node.right;
                stack.push(cur);
            }
        }
        while (!helper.isEmpty()) {
            ans.add(helper.pop().val);
        }
        return ans;
    }
}

測評鏈接:LeetCode 145. Binary Tree Postorder Traversal

更多

算法和數據結構筆記

參考資料

算法和數據結構體系班-左程雲


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM