Morris遍歷二叉樹
阿新 • • 發佈:2021-07-18
所謂Morris遍歷,就是建立線索二叉樹,然後在遍歷的同時邊建邊拆。
主要思路就是,我先拿到當前節點,然後設定一個mostRight指向當前節點的左子樹,然後不斷地找右子樹(這樣做是為了找到當前節點的直接前驅節點)。找到之後,如果這個節點的右孩子指向為空,則指向當前節點,這就是建立線索二叉樹;同時,為了不破壞二叉樹的結構,當這個節點右孩子指向為當前節點時,我們就要把線索斷掉,這就是拆。
左子樹遍歷完後,我們就需要遍歷右子樹。
具體可以看看視訊教程:
我們直接來看程式碼:
1 package com.hw.list0710; 2 3 public class Morris {4 static class TreeNode{ 5 TreeNode left; 6 TreeNode right; 7 int val; 8 public TreeNode(int val, TreeNode left, TreeNode right){ 9 this.val = val; 10 this.left = left; 11 this.right = right; 12 } 13 }14 15 /** 16 * 先序遍歷線索二叉樹 17 * @param cur 18 */ 19 private static void morrisPre(TreeNode cur){ 20 if(cur == null){ 21 return; 22 } 23 TreeNode mostRight = null; 24 while(cur != null) 25 { 26 mostRight = cur.left;27 if(mostRight != null){ 28 while(mostRight.right != null && mostRight.right != cur) 29 { 30 mostRight = mostRight.right; 31 } 32 if(mostRight.right == null){ //建立線索指標 33 mostRight.right = cur; 34 System.out.print(cur.val+" "); 35 cur = cur.left; 36 continue; 37 }else{ 38 mostRight.right = null; //刪除線索指標 39 } 40 }else{ 41 System.out.print(cur.val+" "); 42 } 43 cur = cur.right; //左邊沒了,要到右邊;左邊遍歷完了,也要到右邊 44 } 45 } 46 47 /** 48 * 中序遍歷線索二叉樹 49 * @param cur 50 */ 51 private static void morrisMid(TreeNode cur){ 52 if(cur == null){ 53 return; 54 } 55 TreeNode mostRight = null; 56 while(cur != null) 57 { 58 mostRight = cur.left; 59 if(mostRight != null){ 60 while(mostRight.right != null && mostRight.right != cur) 61 { 62 mostRight = mostRight.right; 63 } 64 if(mostRight.right == null){ 65 mostRight.right = cur; 66 cur = cur.left; 67 continue; 68 }else{ 69 System.out.print(cur.val+" "); 70 mostRight.right = null; 71 } 72 }else{ 73 System.out.print(cur.val+" "); 74 } 75 cur = cur.right; 76 } 77 } 78 79 /** 80 * 反轉連結串列 81 * @param head 82 * @return 83 */ 84 private static TreeNode reverse(TreeNode head){ 85 TreeNode pre = null; 86 TreeNode cur, next; 87 cur = head; 88 while(cur != null) 89 { 90 next = cur.right; 91 cur.right = pre; 92 pre = cur; //指向當前節點的上一個節點的指標前移 93 cur = next; 94 } 95 return pre; 96 } 97 98 /** 99 * 列印連結串列節點 100 * @param head 101 */ 102 private static void printNode(TreeNode head){ 103 TreeNode tail = reverse(head); 104 while(tail != null) 105 { 106 System.out.print(tail.val+" "); 107 tail = tail.right; 108 } 109 reverse(tail); 110 } 111 112 /** 113 * 後序遍歷線索二叉樹 114 * @param cur 115 */ 116 private static void morrisLast(TreeNode cur){ 117 if(cur == null){ 118 return; 119 } 120 TreeNode root = cur; 121 TreeNode mostRight = null; 122 while(cur != null) 123 { 124 mostRight = cur.left; 125 if(mostRight != null){ 126 while(mostRight.right != null && mostRight.right != cur) 127 { 128 mostRight = mostRight.right; 129 } 130 if(mostRight.right == null){ 131 mostRight.right = cur; 132 cur = cur.left; 133 continue; 134 }else{ 135 mostRight.right = null; 136 printNode(cur.left); 137 } 138 } 139 cur = cur.right; 140 } 141 printNode(root); 142 } 143 144 public static void main(String[] args) { 145 TreeNode node6 = new TreeNode(6, null, null); 146 TreeNode node7 = new TreeNode(7, null, null); 147 TreeNode node5 = new TreeNode(5, node6, node7); 148 TreeNode node4 = new TreeNode(4, null, null); 149 TreeNode node2 = new TreeNode(2, node4, node5); 150 TreeNode node3 = new TreeNode(3, null, null); 151 TreeNode node1 = new TreeNode(1, node2, node3); 152 System.out.print("先序遍歷:"); 153 morrisPre(node1); 154 System.out.println(); 155 System.out.print("中序遍歷:"); 156 morrisMid(node1); 157 System.out.println(); 158 System.out.print("後序遍歷:"); 159 morrisLast(node1); 160 } 161 }