만든 사람 : 2019년 5월 23일 - 5.25
개별 사고 과정의 광범위한 사용하지 않는 쉬운 방법.
이진 트리 분석 다수의 층의 접속점 (균형 이진 트리에 한정되는 것은 아니다) :
BinaryNode <T> P;
완전한 바이너리 트리는 식에 따라 노드 P의 층의 수를 산출 할 수있다
노드 P 노드 i 번째 인 경우 (I> = 0), +1은 층의 수로부터 계산 될 수 H = (LOG2의 I)의 특성에 따라 완전한 바이너리 트리
이진 트리의 공통 노드는, 알고리즘 등 어떤 공식이 존재하지 않는 경우는 층의 수를 계산하려면 :
- 생각 :
- 리스트 탐색을 사용하여 생성 된 레이어
결과 : 각 노드가 유일한 시리얼 번호를 그릴은 층의 수를 판단 할 수 없다
- (타당) 당사국 : 프리앰블 시퀀스 preList를 사용하여 빈 트리를 표시
층 int 배열을 정의
각각이 식별자가 널 (null), 소자 층의 값이면, 두 식별 비어 +1 레벨을 통과 뒤로 탐색 (빈 식별 포함) 소자 현명한 값 -1 층 세 빈 식별 시 층 값 -3
(가능) 예 A :
prelist = (A ^ B의 D G ^ ^^ C E F ^^ ^^)
레벨 [] = 1 2 3 4 4 5 5 5 1 2 3 4 4 3 4 4
(유력한) 실시 예 II :
Prelist = (A ^ B에 E F ^^ C ^ D G ^^)
레벨 [] = (1, 2, 3, 4, 4, 5, 5, 4 , 5, 5, 6, 7, 7, 7, 4)
삼
- (개) 방법 2 : 사용 빈 트리 식별 프리앰블 시퀀스 preList 표시 levelList 얻어진 레벨을 횡단
* ArrayList를 가진 제네릭 대신 배열의
배열 번호 정의 스토리지 계층 구조, 길이는 이진 트리 노드의 수
메인 이송 leveList , 실시 예에 나타낸 방법
(가능) 예 A :
prelist = (A ^ B의 D C E G ^^^ ^^ F ^^)
levelList = (A 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는 A B의 수 있습니다 아이도 C에있을 수 있습니다 아이,하지만 중요한, 확실히 형제가 아닌 아이, 레이어 1의 수 (이것은 이진 트리이기 때문에)
(가능) 예 II :
Prelist = (A ^ B에 E F ^ C ^ D G ^ ^ ^)
levelList = (A B D E F G C)
레벨 [] = (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 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 }