1. 程式人生 > >日常學習隨筆-用鏈表的形式實現普通二叉樹的新增、查找、遍歷(前、中、後序)等基礎功能(側重源碼+說明)

日常學習隨筆-用鏈表的形式實現普通二叉樹的新增、查找、遍歷(前、中、後序)等基礎功能(側重源碼+說明)

新增 rabl super 例子 信息 count TP title 處理

一、二叉樹

1、二叉樹的概念

二叉樹是每個節點最多有兩個子樹的樹結構。通常子樹被稱作“左子樹”(left subtree)和“右子樹”(right subtree),其次序不能任意顛倒。

2、性質

(1)若二叉樹的層次從0開始,則在二叉樹的第i層至多有2^i個結點(i>=0);

(2)高度為k的二叉樹最多有2^(k+1) - 1個結點(k>=-1)。 (空樹的高度為-1);

(3)對任何一棵二叉樹,如果其葉子結點(度為0)數為m, 度為2的結點數為n, 則m = n + 1。

二、二叉樹的幾種類型

這裏就不多介紹了,目前的進度了解還不夠深入,後續繼續逐步研究,下面提供一個其他博主介紹的網址:

https://www.cnblogs.com/love-yh/p/7423301.html

三、給出一個自定義的二叉樹的案例(普通二叉樹)

技術分享圖片

二叉樹類:MyTreeDefin.java

  1 package com.xfwl.algorithmAnalysis.trees;
  2 /**
  3  * 二叉樹結構分析
  4  * @function  日常學習測試
  5  * @author 小風微涼
  6  * @time  2018-5-20 下午12:28:50
  7  */
  8 public class MyTreeDefin<T extends Comparable<? super
T>>{ 9 /** 10 * 每棵樹都有一個根節點 11 */ 12 private BinaryNode<T> root; 13 /** 14 * 整棵樹的節點個數 15 */ 16 private int nodeCount; 17 /** 18 * 二叉樹構造器 19 */ 20 public MyTreeDefin(){ 21 this.reset(); 22 } 23 /** 24 * 重置整棵樹的結構
25 */ 26 private void reset(){ 27 //二叉樹的根節點初始化 28 root=null; 29 //二叉樹的節點總數:歸0 30 this.nodeCount=0; 31 } 32 /** 33 * 清空整棵二叉樹 34 * @return 35 */ 36 public boolean makeEmpty(){ 37 this.reset(); 38 return this.isEmpty(); 39 } 40 /** 41 * 獲取樹的節點個數 42 * @return 43 */ 44 public int getSize(){ 45 return this.nodeCount; 46 } 47 /** 48 * 判斷整棵樹是否為空樹 49 * @return 50 */ 51 public boolean isEmpty(){ 52 return this.nodeCount==0?true:false; 53 } 54 /** 55 * 判斷二叉樹中指定節點後面是否包含指定數據 56 * @param target 檢索數據target 57 * @param node 指定的節點(包含當前節點) 58 * @return 59 */ 60 public boolean contains(T target,BinaryNode<T> node){ 61 //判空檢查 62 if(node==null){ 63 return false; 64 } 65 //先和當前節點的數據比較 66 int compareResult=target.compareTo(node.elem); 67 if(compareResult>0){//進入右子樹中繼續判斷 68 return contains(target,node.right); 69 }else if(compareResult<0){//進入左子樹中繼續判斷 70 return contains(target,node.left); 71 }else{//相等 72 return true; 73 } 74 } 75 /** 76 * 從根節點開始查找整棵樹是否包含指定的數據 77 * @param target 檢索數據target 78 * @return 79 */ 80 public boolean contains(T target){ 81 return this.contains(target, this.root); 82 } 83 /** 84 * 查找整棵樹中的最小數據 85 * 左子樹最後一個節點數據 86 * @return 87 */ 88 public T findMin(){ 89 return this.findMin(this.root).elem; 90 } 91 /** 92 * 查找指定樹節點下面的最小節點[查找指定節點後面的最小節點] 93 * @param node 指定的節點 94 * @return 95 */ 96 public BinaryNode<T> findMin(BinaryNode<T> node){ 97 //如果節點為空 98 if(node==null){ 99 return null; 100 }else if(node.left==null){//遞歸基準情況 101 return node; 102 }else{//遞歸流程 103 return findMin(node.left); 104 } 105 } 106 /** 107 * 查找指定樹節點下面的最大節點[最大的數據在右子樹的最深葉子節點] 108 * @param node 指定的查找起點節點 109 * @return 110 */ 111 public BinaryNode<T> findMax(BinaryNode<T> node){ 112 //如果節點為空 113 if(node==null){ 114 return null; 115 }else if(node.right==null){//遞歸基準情況 116 return node; 117 }else{//遞歸流程 118 return findMax(node.right); 119 } 120 } 121 /** 122 * 查找整棵樹中的最大數據 123 * @return 124 */ 125 public T findMax(){ 126 return this.findMax(this.root).elem; 127 } 128 /** 129 * 為二叉樹添加新的節點(對外) 130 * @param data 要添加的數據 131 * @return 132 */ 133 public BinaryNode<T> add(T data){ 134 if(this.isEmpty()){ 135 this.nodeCount++; 136 this.root=new BinaryNode<>(data,null,null); 137 return this.root; 138 }else{ 139 this.nodeCount++; 140 return this.add(data, this.root); 141 } 142 } 143 /** 144 * 為二叉樹添加新的節點(對內) 145 * @param data 要添加的數據 146 * @param curNode 要添加的節點(遞歸比較) 147 */ 148 private BinaryNode<T> add(T data,BinaryNode<T> curNode){ 149 //如果節點不存在:遞歸基準情況 150 if(curNode==null){ 151 return new BinaryNode<>(data,null,null); 152 } 153 //按照:左>根>右 的大小順序插入二叉樹中 154 //比較起點:先和根節點數據比較 155 int compareResult=data.compareTo(curNode.elem); 156 if(compareResult<0){//走左子樹 157 System.out.println("左<--"); 158 curNode.left=this.add(data,curNode.left); 159 }else if(compareResult>0){//走右子樹 160 System.out.println("-->右"); 161 curNode.right=this.add(data,curNode.right); 162 }else{//如果添加的節點數據和當前比較的根節點相同 163 //不做任何處理,可在此繼續擴展 164 } 165 //返回的是根節點 166 return curNode; 167 } 168 /** 169 * 非遞歸添加樹節點 170 * @param data 節點數據 171 * @return 172 */ 173 public void push(T data){ 174 if(this.isEmpty()){//空樹結構 175 this.nodeCount++; 176 this.root=new BinaryNode<>(data,null,null); 177 }else{//至少含有一個根節點 178 BinaryNode<T> tmpNode =this.root; 179 System.out.println("--------------------根節點數據:"+tmpNode.elem+",--------------------"); 180 while(true){ 181 System.out.println("while----:tmpNode.elem="+tmpNode.elem+",data="+data); 182 int compareResult=data.compareTo(tmpNode.elem); 183 if(compareResult<0){//走左子樹 184 System.out.println("左<--"); 185 if(tmpNode.left==null){ 186 tmpNode.left=new BinaryNode<>(data,null,null); 187 break; 188 } 189 tmpNode=tmpNode.left; 190 }else if(compareResult>0){//走右子樹 191 System.out.println("-->右"); 192 if(tmpNode.right==null){ 193 tmpNode.right=new BinaryNode<>(data,null,null); 194 break; 195 } 196 tmpNode=tmpNode.right; 197 }else{//替換當前節點數據(壓入相同數據,沒改變) 198 //也即不做處理 199 break; 200 } 201 } 202 this.nodeCount++; 203 } 204 } 205 /** 206 * 移除二叉樹中根節點後面的指定數據(所在的節點) 207 * @param data 指定的數據 208 */ 209 public BinaryNode<T> remove(T data){ 210 return this.remove(data, this.root); 211 } 212 /** 213 * [刪除是最難的:慢慢琢磨-琢磨好了-以後另開一篇] 214 * 移除二叉樹中指定節點後面的指定數據(所在的節點) 215 * @param node 指定的節點 216 * @param data 指定的數據 217 */ 218 public BinaryNode<T> remove(T data,BinaryNode<T> node){ 219 //節點判斷 220 if(node==null){ 221 return null; 222 } 223 //開始比較 224 int compareResult=data.compareTo(node.elem); 225 if(compareResult==0){//找到基準情況[剛好找到要刪除的數據節點] 226 /** 227 * 找到這個節點 228 */ 229 } 230 //....算了,考慮的頭比較痛,下次再開一篇專門研究二叉樹刪除的案例 231 return null; 232 } 233 /** 234 * 打印樹結構信息 235 * @param index 遍歷的類型 236 * 一般用到的遍歷方式有三種: 237 * (1)前序遍歷 0 238 * (2)中序遍歷 1 239 * (3)後序遍歷 2 240 */ 241 public void printTree(int index){ 242 String type=(index==0?"前序":index==1?"中序":"後序")+"遍歷"; 243 System.out.println("------------【開始遍歷打印·"+type+"】------------"); 244 switch(index){ 245 case 0:preOrder(this.root);break; 246 case 1:inOrder(this.root);break; 247 case 2:postOrder(this.root);break; 248 } 249 System.out.println("------------【打印結束】------------"); 250 } 251 /** 252 * 前序遍歷 253 * @param node 遍歷的起始節點 254 * 采用遞歸思想 255 * 對左子節點進行遍歷 256 * 對右子節點進行遍歷 257 * 遞歸基值是node是否是null 258 */ 259 private void preOrder(BinaryNode<T> node) 260 { 261 if(node==null){ 262 return; 263 }else{ 264 System.out.print(node.elem+" ");//輸出數據節點信息 265 preOrder(node.left); 266 preOrder(node.right); 267 } 268 } 269 /** 270 * 中序遍歷 271 * @param node 272 */ 273 private void inOrder(BinaryNode<T> node){ 274 if(node==null){ 275 return; 276 }else{ 277 inOrder(node.left); 278 System.out.print(node.elem+" "); 279 inOrder(node.right); 280 } 281 } 282 /** 283 * 後序遍歷 284 * @param node 285 */ 286 private void postOrder(BinaryNode<T> node){ 287 if(node==null){ 288 return; 289 }else{ 290 postOrder(node.left); 291 postOrder(node.right); 292 System.out.print(node.elem+" "); 293 } 294 } 295 /** 296 * 獲取指定節點的數據 297 * @param node 298 * @return 299 */ 300 public T getElem(BinaryNode<T> node){ 301 if(node==null){ 302 return null; 303 } 304 return node.elem; 305 } 306 /** 307 * 內置一個樹節點類 308 */ 309 private static class BinaryNode<T>{ 310 /** 311 * 樹節點存放數據域 312 */ 313 T elem; 314 /** 315 * 左子樹節點域 316 */ 317 BinaryNode<T> left; 318 /** 319 * 右子樹節點域 320 */ 321 BinaryNode<T> right; 322 /** 323 * 構造器 324 */ 325 public BinaryNode(T elem,BinaryNode<T> left,BinaryNode<T> right){ 326 this.elem=elem; 327 this.left=left; 328 this.right=right; 329 } 330 } 331 } 332

測試類:Test.java

 1 package com.xfwl.algorithmAnalysis.trees;
 2 
 3 public class Test {
 4     /**
 5      * @param args
 6      */
 7     public static void main(String[] args) {
 8         //創建一棵樹
 9         MyTreeDefin<Integer> tree=new MyTreeDefin<>();
10         //壓入數據
11         tree.push(5);
12         tree.push(2);
13         tree.push(4);
14         tree.push(8);
15         tree.push(7);
16         tree.push(10);
17         tree.push(3);
18         tree.push(9);
19         tree.push(6);
20         tree.push(1);
21         System.out.println(tree.getSize());
22         //開始遍歷顯示
23         tree.printTree(0);
24         tree.printTree(1);
25         tree.printTree(2);
26         //刪除
27     }
28 }

測試結果:

--------------------根節點數據:5,--------------------
while----:tmpNode.elem=5,data=2<--
--------------------根節點數據:5,--------------------
while----:tmpNode.elem=5,data=4<--
while----:tmpNode.elem=2,data=4
-->--------------------根節點數據:5,--------------------
while----:tmpNode.elem=5,data=8
-->--------------------根節點數據:5,--------------------
while----:tmpNode.elem=5,data=7
-->while----:tmpNode.elem=8,data=7<--
--------------------根節點數據:5,--------------------
while----:tmpNode.elem=5,data=10
-->while----:tmpNode.elem=8,data=10
-->--------------------根節點數據:5,--------------------
while----:tmpNode.elem=5,data=3<--
while----:tmpNode.elem=2,data=3
-->while----:tmpNode.elem=4,data=3<--
--------------------根節點數據:5,--------------------
while----:tmpNode.elem=5,data=9
-->while----:tmpNode.elem=8,data=9
-->while----:tmpNode.elem=10,data=9<--
--------------------根節點數據:5,--------------------
while----:tmpNode.elem=5,data=6
-->while----:tmpNode.elem=8,data=6<--
while----:tmpNode.elem=7,data=6<--
--------------------根節點數據:5,--------------------
while----:tmpNode.elem=5,data=1<--
while----:tmpNode.elem=2,data=1<--
10
------------【開始遍歷打印·前序遍歷】------------
5 2 1 4 3 8 7 6 10 9 ------------【打印結束】------------
------------【開始遍歷打印·中序遍歷】------------
1 2 3 4 5 6 7 8 9 10 ------------【打印結束】------------
------------【開始遍歷打印·後序遍歷】------------
1 3 4 2 6 7 9 10 8 5 ------------【打印結束】------------

四、總結一下

  最近比較忙,學習進度明顯感到有點延遲了,還是得抓緊時間啊!上面的測試例子並沒有寫“二叉樹的刪除”功能,刪除也比較麻煩,分為很多種情形,需要仔細分析,此篇就不在分析說明了,以後再慢慢研究,要學的東西還很多,慢慢來吧!

日常學習隨筆-用鏈表的形式實現普通二叉樹的新增、查找、遍歷(前、中、後序)等基礎功能(側重源碼+說明)