1. 程式人生 > >數據結構 遞歸和非遞歸方式實現二叉樹先序、中序和後序遍歷

數據結構 遞歸和非遞歸方式實現二叉樹先序、中序和後序遍歷

nor post 後序遍歷 order else 對象 二叉樹先序 bre print

  二叉樹的先序遍歷順序是根、左、右;中序遍歷順序是左、根、右;後序遍歷順序是左、右、根。

  遞歸方式實現如下:

 1 public class TreeNode {
 2     private int value;
 3     private TreeNode left, right;
 4     
 5     public TreeNode(int data) {
 6         value = data;
 7     }
 8     
 9     // 遞歸方式實現先序遍歷
10     public void preorder(TreeNode treeNode) {
11 if (treeNode == null) { 12 return; 13 } 14 15 System.out.println(treeNode.value + " "); 16 preorder(treeNode.left); 17 preorder(treeNode.right); 18 } 19 20 // 遞歸方式實現中序遍歷 21 public void inorder(TreeNode treeNode) { 22 if
(treeNode == null) { 23 return; 24 } 25 26 inorder(treeNode.left); 27 System.out.println(treeNode.value + " "); 28 inorder(treeNode.right); 29 } 30 31 // 遞歸方式實現後序遍歷 32 public void postorder(TreeNode treeNode) { 33 if (treeNode == null
) { 34 return; 35 } 36 37 postorder(treeNode.left); 38 postorder(treeNode.right); 39 System.out.println(treeNode.value + " "); 40 } 41 }

  遞歸方式能解決的問題都能用非遞歸方式來解決,因為遞歸方式通過函數棧來保存信息,普通的棧或隊列也能達到相同效果。

  

  非遞歸方式實現先序遍歷,步驟如下:

  1 如果當前結點為空,則結束。

  2 創建實現了Queue接口的LinkedList對象,引用為queue。

  3 當前結點入隊列。

  4 隊頭結點出隊列,打印其結點值。其左右非空孩子結點入隊列。

  5 重復步驟4,直到queue為空。

  舉例:

  技術分享圖片

  結點1入隊列,然後出隊列並打印。結點2和3入隊列。隊列中結點(從隊頭到隊尾,下同):2、3。

  結點2出隊列並打印,結點4和5入隊列。隊列中結點:3、4、5。

  結點3出隊列並打印,結點6和7入隊列。隊列中結點:4、5、6、7。

  結點4出隊列並打印。隊列中結點:5、6、7。

  結點5出隊列並打印。隊列中結點:6、7。

  結點6出隊列並打印。隊列中結點:7。

  結點7出隊列並打印。

  Java代碼:

 1 // 非遞歸方式實現先序遍歷
 2 public void preOrder(TreeNode cur) {
 3     if (cur != null) {
 4         Queue<TreeNode> queue = new LinkedList<TreeNode>();
 5         queue.add(cur);
 6         
 7         while (!queue.isEmpty()) {
 8             cur = queue.remove();
 9             System.out.println(cur.value + " ");
10             
11             TreeNode left = cur.left, right = cur.right;
12             if (left != null) {
13                 queue.add(left);
14             }
15             if (right != null) {
16                 queue.add(right);
17             }
18         }
19     }
20 }

  

  非遞歸方式實現中序遍歷,步驟如下:

  1 如果當前結點為空,則結束。

  2 創建實現了Deque接口的LinkedList對象,引用為stack。

  3 當前結點入棧,左孩子結點不斷入棧,直到沒有左孩子結點。

  4 棧頂結點出棧,打印其結點值。如果有右孩子結點,則把它設為當前結點;否則,重復該步驟,直到有右孩子結點或者stack為空。

  5 重復步驟3和4。

  舉例:

  二叉樹看上圖(下同)。

  結點1、2和4入棧。棧中結點(從棧頂到棧底,下同):4、2、1。

  結點4和2出棧並打印,結點5入棧。棧中結點:5、1。

  結點5和1出棧並打印,結點3和6入棧。棧中結點:6和3。

  結點6和3出棧並打印,結點7入棧。棧中結點:7。

  結點7出棧。

  Java代碼:

 1 // 非遞歸方式實現中序遍歷
 2 public void inOrder(TreeNode cur) {
 3     if (cur != null) {
 4         Deque<TreeNode> stack = new LinkedList<TreeNode>();
 5         while (true) {
 6             // 已保證當前結點非空
 7             stack.addFirst(cur);
 8             for (cur = cur.left; cur != null; cur = cur.left) {
 9                 stack.addFirst(cur);
10             }
11             
12             while (true) {
13                 // 當前結點出棧並打印
14                 cur = stack.removeFirst();
15                 System.out.println(cur.value + " ");
16                 
17                 TreeNode right = cur.right;
18                 if (right != null) {
19                     cur = right;
20                     break;
21                 } else if (stack.isEmpty()) {
22                     return;
23                 }
24             }
25         }
26     }
27 }

  

  非遞歸方式實現中序遍歷,步驟如下:

  1 如果當前結點為空,則結束。

  2 創建兩個實現了Deque接口的LinkedList對象,引用為stack1和stack2。

  3 當前結點入棧stack1,棧頂結點出棧。該結點入棧stack2,該結點的非空左右孩子結點入棧stack1。

  4 重復步驟3,直到stack1為空。

  5 stack2不斷出棧並打印棧頂結點值,直到stack2為空。

  舉例:

  結點1入棧stack1。

  結點1出棧,入棧stack2。結點2和3入棧stack1。

  結點3出棧,入棧stack2。結點6和7入棧stack1。

  結點7出棧,入棧stack2。

  結點6出棧,入棧stack2。

  結點2出棧,入棧stack2。結點4和5入棧stack1。

  結點5出棧,入棧stack2。

  結點4出棧,入棧stack2。

  結點4、5、2、6、7、3、1出棧並打印。

  Java代碼:

 1 // 非遞歸方式實現後序遍歷
 2 public void postOrder(TreeNode cur) {
 3     if (cur != null) {
 4         Deque<TreeNode> stack1 = new LinkedList<TreeNode>();
 5         Deque<TreeNode> stack2 = new LinkedList<TreeNode>();
 6         
 7         stack1.addFirst(cur);
 8         while (!stack1.isEmpty()) {
 9             cur = stack1.removeFirst();
10             stack2.addFirst(cur);
11             
12             TreeNode left = cur.left, right = cur.right;
13             if (left != null) {
14                 stack1.addFirst(left);
15             }
16             if (right != null) {
17                 stack1.addFirst(right);
18             }
19         }
20         
21         while (!stack2.isEmpty()) {
22             System.out.println(stack2.removeFirst().value + " ");
23         }
24     }
25 }

  參考資料

  《程序員代碼面試指南 IT名企算法與數據結構題目最優解》P88-95

數據結構 遞歸和非遞歸方式實現二叉樹先序、中序和後序遍歷