作成:2019年5月23日 - 5.25を
個々の思考プロセス、ないの普及に簡単な方法。
バイナリツリーを分析する層の数の接続点(バランスバイナリツリーに限定されるものではありません)。
BinaryNode <T>のp;
完全なバイナリツリーは、式に従ってノードPの層の数を計算することができます
ノードPは、I番目のノード(I> = 0)である場合、H =(LOG2 i)を+1の性質に応じて、完全なバイナリツリーは、層の数から算出することができます
バイナリツリーの共通ノードは、アルゴリズムのようないかなる式は、存在しない場合の層の数を計算します:
- 考えます:
- リスト・トラバーサルを使用して得られた層
結果:各ノードの唯一のドローシリアル番号、層の数を決定することができません
- (実現可能)パーティー:プリアンブル系列preListを使用してマークされ、空の木
層のint配列を定義します。
(空の識別を含む)要素ごとバックトラバーサル、各識別子がヌルである+1レベル、素子層の値を横切る、2つの識別が空で、値-1層、3つの空識別場合レイヤ値-3
(可能な)例:
prelist =(BとD ^ G ^ ^ ^ C E ^ ^ F ^ ^)
レベル[] = 1 2 3 4 4 5 5 5 2 3 4 4 3 4 4
(生)実施例II:
Prelist =(BとE ^ F ^ ^ C ^ D G ^ ^ ^ ^)
レベル[] =(1、2、3、4、4、5、5、 4、 5、5、6、7、7、7、4)
3
- (改善)方法2:使用して空のツリー識別プリアンブルシーケンスpreListマークlevelList得られたレベルを横切ります
* ArrayListを持つジェネリック配列の代わりに
配列番号定義されたストレージ階層は、長さは、バイナリツリーノードの数であります
主トラバースleveList 、実施例に示す工程
(可能な)例:
prelist =(B D ^ G ^^^ C E ^^ F ^^)
levelList =(B C D E F G)
レベル[] = 1 2 2 3 3 3 4
プロセス:
唯一のルートノード、第1の層の数は確かに1
第B- 層2は確かです。
LevelListのインデックスポイントC 、preListの添え字は、D点と等しくない、同じ層数、及びpreListの場合、添字不変。
* 理由:
levelist B内には、次のCであるか、CはBのある子供、またはCがBである兄弟。preListにおいて、Bは、次の要素は、C(CはないがBではないの子供)ので、Cは間違いなくBである兄弟
LevelListのインデックスポイントD 、preListのインデックスがまだDある層+ 1の数に等しく、(Dの層である。3 )、preList 添字+ 1 (点G )
* なぜ:D C内には、背後にある、DはBのかもしれ子もCのかもしれ子が、重要なのは、確かではないの兄弟ではない子、レイヤ1の数(それは、二分木であるため)
(可能な)例II:
Prelist =(BとE ^ F ^ ^ C ^ D G ^ ^^ ^)
levelList =(B E C F D G)
レベル[] =(1、2、3、3、4、4、4)
(改善された実行可能な)例3:
Prelist =(100、40、19、^^、21、^^、60、28、11、5、2、^^、3、^^、6、17、7、^^、10、^^、32 、^^)
levelList =(100、40、60、19、21、28、32、11、17、5、6、7、10、2、3)
レベル[] =(1、2、2、3、 4、4、4、4、4、4、4、4、4、4、4 )
3 3 3 4 4 5 5 6 6
改进1:(加条件)若prelist中遍历到的元素前有连续两个空标识,层数也不变(不论元素是否相等),preList下标+1
改进2:若在preList中遍历到levelList指向元素之前遍历过的元素,直接该元素
(不可以只是跳过,因为还要判断preFlag指向前两个元素是否为空标识^)
过程:
(部分)
LevelList中指标指向21,Prelist指向21,相等,但因为prelist的21前有两个连续空标识,所以层数不变;
*为什么:
LevelList中21在19的后面,21可能是19的孩子,21也可能是19的兄弟,看preList,虽然指向21,但前有两个空标识,说明21肯定不是19的孩子(两个孩子位被空标识占去),21只可能是19的兄弟,所以层数不变。
LevelList中指标指向28,Prelist指向60,因为levelList中60在28之前已经出现过,所以跳过这个元素,preflag++
*为什么:
判断一个元素的层数只需要知道,它与前面一个结点的关系(孩子还是兄弟),无需知道更前面哪些元素的信息。由于这个前面出现过的元素的层数已经计算得出,可以直接删去该元素。
例四:
preList= (18,7, ^^ , 11, 5, ^^, 6, 2,^^, 4,^^)
levelList= (18, 7, 11, 5, 6, 2, 4 )
Level[]= ( 1, 2, 2, 3, 3, 4, 4 )
算法实现代码:(已测试)
1 /** 2 * @title: nodelevel 3 * @description: get a given node's level 4 * @author: Navis 5 * @date: May 25, 2019 6:04:49 PM 6 * @param p as root node 7 * @return int :level 8 * @throws:IllegalArgumentException:p==null 9 */ 10 public int nodelevel(BinaryNode<T> p) { 11 if (this.root == null) 12 return -1; 13 if (p == null) 14 throw new IllegalArgumentException("p==null"); 15 16 int nodeCount = this.getNodeConut(); 17 int[] lev = new int[nodeCount]; 18 19 ArrayList preList = this.getPrelist(this.root); 20 ArrayList levelList = this.levelList(); 21 int nodeNum = levelList.indexOf(p.data); // p在levelList中的元素位置 22 23 lev[0] = 1;// 根结点只有一个,所以第一个元素层数是1 24 lev[1] = 2;// 第二个元素的层数是2; 25 26 int preFlag = 2; 27 Object firstBefore = preList.get(0); 28 Object secondBefore = preList.get(1); 29 // 计算层数数组lev[] 30 for (int i = 2; i < levelList.size(); i++) {// 从第3个元素开始 31 for (int k = 0; k < i; k++) {// 若preFlag指向元素,在levelList的第i个元素前已经出现过,则删除该元素 32 if (preList.get(preFlag).equals(levelList.get(k))) { 33 preList.remove(preFlag); 34 35 k = 0;// k重新开始循环,判断更新后的preFlag位置元素是否之前出现过 36 } 37 } 38 if (firstBefore.equals("^") && secondBefore.equals("^")) { 39 lev[i] = lev[i - 1]; 40 41 preFlag++; 42 while (preList.get(preFlag).equals("^")) { 43 preFlag++; 44 } 45 firstBefore = preList.get(preFlag - 1);// preFlag指向元素的前面第一个元素 46 secondBefore = preList.get(preFlag - 2);// preFlag指向元素的前面第二个元素 47 } else { 48 if (preList.get(preFlag).equals(levelList.get(i))) {// 相等 49 lev[i] = lev[i - 1] + 1; 50 51 preFlag++; 52 while (preList.get(preFlag).equals("^")) {// 跳过^空标识,指向有值元素 53 preFlag++; 54 if (preFlag >= preList.size()) {// 防止preList后面全是^空标识,导致一直循环下去 55 break; 56 } 57 } 58 firstBefore = preList.get(preFlag - 1); 59 secondBefore = preList.get(preFlag - 2); 60 } else {// 不相等 61 lev[i] = lev[i - 1]; 62 } 63 } 64 // System.out.println(levelList.get(i) + ":" + lev[i]); 65 } 66 return lev[nodeNum]; 67 } 68 69 70 /** 71 * @title: getNodeConut 72 * @description: getNodeCount 73 * @author: Navis 74 * @date: May 24, 2019 10:55:13 AM 75 * @return int nodeCount 76 */ 77 public int getNodeConut() { 78 int nodeCount = 0; 79 ArrayList prelist = this.getPrelist(this.root);// 得到带有空子树标识的prelist 80 81 for (int i = 0; i < prelist.size(); i++) { 82 if (prelist.get(i) != "^") 83 nodeCount++; 84 } 85 86 return nodeCount; 87 } 88 89 /** 90 * @title: getPrelist 91 * @description: getPrelist; with emptySubTree sign 92 * @author: Navis 93 * @date: May 24, 2019 10:30:34 AM 94 * @param BinaryNode<T> p 95 * @return ArrayList prelist 96 */ 97 public ArrayList getPrelist(BinaryNode<T> p) { 98 ArrayList prelist = new ArrayList(); 99 preorder(prelist, p); 100 101 return prelist; 102 } 103 104 /** 105 * @title: levelList 106 * @description: get levelList;levelOrder 107 * @author: Navis 108 * @date: May 24, 2019 11:54:07 AM 109 * @return ArrayList levelList 110 */ 111 public ArrayList levelList() { 112 LinkedQueue<BinaryNode<T>> queue = new LinkedQueue<>();// 空队列 113 BinaryNode<T> p = this.root;// 根结点不入队 114 ArrayList levelList = new ArrayList(); 115 116 while (p != null) { 117 levelList.add(p.data); // 将已出队结点p的元素值加入levelList 118 119 if (p.left != null) 120 queue.add(p.left);// p的左孩子入队 121 if (p.right != null) 122 queue.add(p.right);// p的右孩子入队 123 124 p = queue.poll();// p指向出队结点,若队列为空返回null 125 } 126 return levelList; 127 }