樹的后序遍歷的兩種實現


今天介紹一下樹的后序遍歷

什么是后序遍歷

  所謂遍歷就是將集合中的所有元素都訪問一遍,由於樹是一種非線性結構,所以它的遍歷方式有很多種:

  • 前序遍歷 :根左右
  • 中序遍歷 :左根右
  • 后序遍歷 :左右根
  • 按層遍歷 :逐層訪問

  接下來我們用動圖的方式,看一下樹的后序遍歷過程:

遞歸

  我們將動圖翻譯成代碼,就得到了遞歸的實現方法
  定義樹

1class TreeNode{
2    public TreeNode left;
3    public TreeNode right;
4    public int val;
5
6    public TreeNode(int val){
7        this.val = val;
8    }
9}

  方法實現

1 private static void function(TreeNode head){
2        if(head == null){
3            return;
4        }
5        function(head.left);
6        function(head.right);
7        System.out.println(head.val);
8    }

  可以看到遞歸的方法非常的簡單,甚至看一遍就可以記住了,通常這道題到這為止就算做完了,但是你真的理解這段代碼嗎?或者說如果不用遞歸,你可以用循環的方式實現這道題嗎?

循環

  任何用遞歸做的題,我們用循環的方式都可以解決。解決的思路大體相同,用代碼實現遞歸的調用棧,我們依然要對照着圖示來看,首先我們將樹的所有左節點入棧,然后出棧,去遍歷它的右節點,將右節點入棧,以此重復上述的過程。具體代碼如下(推薦使用方法二,可大概看一下,直接去看方法二):

 1    private static void function(TreeNode head) {
2        if (head == null) {
3            return;
4        }
5        Stack<TreeNode> stack = new Stack<>();
6        Stack<TreeNode> repeatStack = new Stack<>();
7        TreeNode cur = head;
8        pushLeftNode(stack, cur);
9        while (!stack.empty()) {
10            cur = stack.peek();
11            if (!repeatStack.empty() && repeatStack.peek() == cur) {
12                repeatStack.pop();
13                stack.pop();
14                System.out.println(cur.val);
15            } else {
16                if (cur.right != null) {
17                    repeatStack.push(cur);
18                    pushLeftNode(stack, cur.right);
19                } else {
20                    cur = stack.pop();
21                    System.out.println(cur.val);
22                }
23            }
24        }
25    }
26
27    private static void pushLeftNode(Stack<TreeNode> stack, TreeNode node) {
28        stack.push(node);
29        while (node.left != null) {
30            stack.push(node.left);
31            node = node.left;
32        }
33    }

  這種做法比較符合直覺,我們模擬出了一個調用棧,然后借助另一個repeatStack,用來過濾遍歷過的元素,防止元素重復遍歷的過程。


  還有其他的循環方法,我們可以對方法一的stack進行拆分,拆分出的2個棧,一個用來存儲結果,一個用來計算。

 

 1private static void function(TreeNode head) {
2        if (head == null) {
3            return;
4        }
5        Stack<TreeNode> stack1 = new Stack<>();
6        Stack<TreeNode> stack2 = new Stack<>();
7        stack1.push(head);
8        while (!stack1.empty()) {
9            TreeNode cur = stack1.pop();
10            stack2.push(cur);
11            if(cur.left != null){
12                stack1.push(cur.left);
13            }
14            if(cur.right != null){
15                stack1.push(cur.right);
16            }
17        }
18
19        while(!stack2.empty()){
20            System.out.println(stack2.pop().val);
21        }
22    }


免責聲明!

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



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