今天介紹一下樹的后序遍歷
什么是后序遍歷
所謂遍歷就是將集合中的所有元素都訪問一遍,由於樹是一種非線性結構,所以它的遍歷方式有很多種:
- 前序遍歷 :根左右
- 中序遍歷 :左根右
- 后序遍歷 :左右根
- 按層遍歷 :逐層訪問
接下來我們用動圖的方式,看一下樹的后序遍歷過程:

遞歸
我們將動圖翻譯成代碼,就得到了遞歸的實現方法
定義樹
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 }