二叉樹—刪除節點
1)刪除節點是葉子節點,刪除該節點
2)刪除節點是非葉子節點,則刪除該子樹
思路:
1、考慮若樹是空樹root,如果只有一個root節點,則等價將二叉樹置空
2、因二叉樹是單向的,所以判斷當前節點的子節點是否需要刪除,而不能判斷當前這個節點是不是需要刪除節點
3、如果當前節點的左子節點不為空,並且左子節點就是要刪除節點,就將this.left =null;
並且就返回(結束遞歸刪除)
4、如果當前節點的右子節點不為空,並且右子節點就是要刪除節點,就將this.right =null;
並且就返回(結束遞歸刪除)
5、若第2和第3步沒有刪除節點,需要向左子樹進行遞歸刪除
6、若第4步也沒有刪除節點,向右子樹進行遞歸刪除
1 public class BinaryTreeDemo { 2 3 public static int PRECOUNT = 0; 4 public static int INFIXCOUNT = 0; 5 public static int POSTCOUNT = 0; 6 public static void main(String[] args) { 7 //先需要創建一棵二叉樹 8 BinaryTree binaryTree = new BinaryTree(); 9 EmpNode root = new EmpNode(1, "aa"); 10 EmpNode emp2 = new EmpNode(2, "bb"); 11 EmpNode emp3 = new EmpNode(3, "cc"); 12 EmpNode emp4 = new EmpNode(4, "dd"); 13 EmpNode emp5 = new EmpNode(5, "ee"); 14 15 //手動創建二叉樹,后面學習遞歸的方式創建二叉樹 16 root.setLeft(emp2); 17 root.setRight(emp3); 18 emp3.setRight(emp4); 19 emp3.setLeft(emp5); 20 21 //測試 22 System.out.println("前序遍歷"); 23 binaryTree.setRoot(root); 24 binaryTree.preOrder(); 25 26 System.out.println("中序遍歷"); 27 binaryTree.setRoot(root); 28 binaryTree.infixOrder(); 29 30 31 System.out.println("后序遍歷"); 32 binaryTree.setRoot(root); 33 binaryTree.postOrder(); 34 35 //前序查找 36 //前序查找次數 37 System.out.println("前序查找方式"); 38 EmpNode resNode = binaryTree.preOrderSearch(5); 39 if (resNode != null){ 40 System.out.printf("找到,信息為no=%d name=%s 查詢次數為%s",resNode.getNo(),resNode.getName(),PRECOUNT); 41 42 }else { 43 System.out.printf("沒找到 no=%d",5); 44 } 45 46 System.out.println(); 47 48 //中序查找 49 //中序查找次數 50 System.out.println("中序查找方式"); 51 EmpNode resNode1 = binaryTree.infixOrderSearch(5); 52 if (resNode1 != null){ 53 System.out.printf("找到,信息為no=%d name=%s 查詢次數為%s",resNode1.getNo(),resNode1.getName(),INFIXCOUNT); 54 55 }else { 56 System.out.printf("沒找到 no=%d",5); 57 } 58 59 System.out.println(); 60 61 //后序查找 62 //后序查找次數 63 System.out.println("后序查找方式"); 64 EmpNode resNode2 = binaryTree.postOrderSearch(5); 65 if (resNode1 != null){ 66 System.out.printf("找到,信息為no=%d name=%s 查詢次數為%s",resNode2.getNo(),resNode2.getName(),POSTCOUNT); 67 68 }else { 69 System.out.printf("沒找到 no=%d",5); 70 } 71 72 73 74 75 } 76 77 } 78 79 //2.定義一個BinaryTree 80 class BinaryTree { 81 private EmpNode root; 82 83 public void setRoot(EmpNode root) { 84 this.root = root; 85 } 86 87 //前序遍歷 88 public void preOrder() { 89 if (this.root != null) { 90 this.root.preOrder(); 91 } else { 92 System.out.println("二叉樹為空,無法遍歷"); 93 } 94 } 95 96 //中序遍歷 97 public void infixOrder() { 98 if (this.root != null) { 99 this.root.infixOrder(); 100 } else { 101 System.out.println("二叉樹為空,無法遍歷"); 102 } 103 } 104 105 //后序遍歷 106 public void postOrder() { 107 if (this.root != null) { 108 this.root.postOrder(); 109 } else { 110 System.out.println("二叉樹為空,無法遍歷"); 111 } 112 } 113 114 //前序查找 115 public EmpNode preOrderSearch(int no){ 116 if (root != null){ 117 return root.preOrderSearch(no); 118 }else { 119 return null; 120 } 121 } 122 123 //中序查找 124 public EmpNode infixOrderSearch(int no){ 125 if (root != null){ 126 return root.infixOrderSearch(no); 127 }else { 128 return null; 129 } 130 } 131 //后序查找 132 public EmpNode postOrderSearch(int no){ 133 if (root != null){ 134 return root.postOrderSearch(no); 135 }else { 136 return null; 137 } 138 } 139 140 //刪除節點 141 public void delNode(int no){ 142 if (root != null){ 143 //如果只有一個root節點,需要立即判斷是不是要刪除節點 144 if (root.getNo() == no){ 145 root = null; 146 }else{ 147 root.delNode(no); 148 } 149 150 }else { 151 System.out.println("空樹,不能刪除"); 152 } 153 } 154 } 155 156 //1.先創建HeroNode 157 class EmpNode { 158 private int no; 159 private String name; 160 private EmpNode left;//默認為null 161 private EmpNode right;//默認為null 162 163 public EmpNode(int no, String name) { 164 this.no = no; 165 this.name = name; 166 } 167 168 public int getNo() { 169 return no; 170 } 171 172 public void setNo(int no) { 173 this.no = no; 174 } 175 176 public String getName() { 177 return name; 178 } 179 180 public void setName(String name) { 181 this.name = name; 182 } 183 184 public EmpNode getLeft() { 185 return left; 186 } 187 188 public void setLeft(EmpNode left) { 189 this.left = left; 190 } 191 192 public EmpNode getRight() { 193 return right; 194 } 195 196 public void setRight(EmpNode right) { 197 this.right = right; 198 } 199 200 @Override 201 public String toString() { 202 return "EmpNode{" + 203 "no=" + no + 204 ", name='" + name + '\'' + 205 '}'; 206 } 207 208 //遞歸刪除節點 209 //1.若刪除的節點是葉子節點,則刪除該節點 210 //2.若刪除的節點是非葉子節點,則刪除該子樹 211 public void delNode(int no){ 212 //思路 213 if (this.left != null && this.left.no == no){ 214 this.left = null; 215 return; 216 } 217 if (this.right != null && this.right.no == no){ 218 this.right = null; 219 return; 220 } 221 222 if (this.left != null){ 223 this.left.delNode(no); 224 //return;寫了return有可能下面向右不執行了 225 } 226 if (this.right != null){ 227 this.right.delNode(no); 228 } 229 } 230 231 //編寫前序遍歷方法 232 233 public void preOrder() { 234 System.out.println(this);//先輸出父節點 235 //遞歸向左子樹前序遍歷 236 if (this.left != null) { 237 this.left.preOrder(); 238 } 239 //遞歸向右子樹前序遍歷 240 if (this.right != null) { 241 this.right.preOrder(); 242 } 243 244 } 245 246 //編寫中序遍歷方法 247 public void infixOrder() { 248 //遞歸向左子樹中序遍歷 249 if (this.left != null) { 250 this.left.infixOrder();//2,1,3,4 251 } 252 //輸出父節點 253 System.out.println(this); 254 //遞歸向右子樹中序遍歷 255 if (this.right != null) { 256 this.right.infixOrder(); 257 } 258 } 259 260 //編寫后序遍歷方法 261 public void postOrder() { 262 if (this.left != null) { 263 this.left.postOrder(); 264 } 265 if (this.right != null) { 266 this.right.postOrder(); 267 } 268 System.out.println(this); 269 } 270 271 /** 272 * @param no 查找no 273 * @return 若找到就返回該Node,若沒找到返回Null 274 */ 275 //前序遍歷查找 276 public EmpNode preOrderSearch(int no) { 277 BinaryTreeDemo.PRECOUNT++; 278 //System.out.println("進入前序查找"); 279 280 //比較當前節點是不是 281 if (this.no == no) { 282 return this; 283 } 284 //判斷當前節點的左子節點是否為空,若不為空,則遞歸前序查找 285 //若左遞歸前序查找,找到節點,則返回 286 287 EmpNode resNode = null; 288 if (this.left != null) { 289 resNode = this.left.preOrderSearch(no); 290 } 291 if (resNode != null) { 292 return resNode; 293 } 294 295 //左遞歸前序查找,找到節點,則返回,否繼續判斷 296 //當前的結點的右子節點是否為空,若為空,則繼續向右遞歸前序查找 297 if (this.right != null) { 298 resNode = this.right.preOrderSearch(no); 299 } 300 return resNode; 301 302 } 303 304 //中序遍歷查找 305 public EmpNode infixOrderSearch(int no) { 306 307 //判斷當前節點的左子節點是否為空,若不為空,則遞歸中序查找 308 EmpNode resNode = null; 309 if (this.left != null) { 310 resNode = this.left.infixOrderSearch(no); 311 } 312 if (resNode != null) { 313 return resNode; 314 } 315 BinaryTreeDemo.INFIXCOUNT++; 316 //若找到,則返回,若沒找到,就和當前節點比較,若是則返回 317 if (this.no == no) { 318 return this; 319 } 320 //否則繼續進行右遞歸的中序查找 321 if (this.right != null) { 322 resNode = this.right.infixOrderSearch(no); 323 } 324 return resNode; 325 326 } 327 328 //后序遍歷查找 329 public EmpNode postOrderSearch(int no) { 330 331 332 //判斷當前節點的左子節點是否為空,若不為空,則繼續遞歸后序查找 333 EmpNode resNode = null; 334 if (this.left != null) { 335 resNode = this.left.postOrderSearch(no); 336 } 337 if (resNode != null) {//說明左子樹找到 338 return resNode; 339 } 340 //若左子樹沒找到,則向右子樹遞歸進行后序遍歷查找 341 if (this.right != null) { 342 resNode = this.right.postOrderSearch(no); 343 } 344 if (resNode != null) { 345 return resNode; 346 } 347 //若左右子樹都沒找到,就比較當前節點是不是 348 BinaryTreeDemo.POSTCOUNT++; 349 if (this.no == no) { 350 return this; 351 } 352 return resNode; 353 } 354 355 }