思路跟前面大体一样,先找出叶子节点的链表。这次增加叶子层次level值。
1、首先找出叶子链表时,已经保证叶子链表中顺序与二叉树中序遍历顺序一致。
2、利用类似二分查找的做法,找出当前层次叶子左半部和右半部的分割点,再找出左半部叶子的最大层次深度,和右半部最大层次深度,计算出最大距离。
然后把左右半部分别分为两半,继续递归。
3、如果当前最大距离大于递归下一层次的最大距离,直接返回,减少递归次数
如:找到叶子链表编号为 2、24、13、14、31,编号的二进制代表该点在二叉树从根出发的路径,maxlevel为5
1、当level为1时,编号二进制最高位1的右边一位,代表该叶子在左子树还是右子树,
那么左半部为2
右半部为24、13、14、31
最大距离为5
2、当level为2时
24、13、14、31分为
左半部24、13
右半部14、31
最大距离为6,停止递归,返回
这个时间复杂度是O(n+mlog m),当二叉树比较接近完全二叉树时,这个方法查找速度比较快。
1 #include <iostream> 2 using namespace std; 3 4 struct Node{ 5 int data; 6 struct Node* left; 7 struct Node* right; 8 //为了测试增加这个函数 9 Node(int val) :data(val), left(NULL), right(NULL) 10 {} 11 }; 12 13 //存放叶子节点的双向链表 14 struct Leaf{ 15 unsigned long id; //给Node链表的节点编号,root为编号1 16 unsigned int level; //叶子节点的层次深度,root为1 17 struct Node* node; //指向的叶子节点 18 struct Leaf* pre; //前驱 19 struct Leaf* next; //后驱 20 }; 21 22 //找出所有叶子节点的递归函数 23 struct Leaf* findleaf(struct Node* node, struct Leaf* tail, unsigned int level, unsigned long id) 24 { 25 if (NULL == node) 26 return tail; 27 if (NULL == node->left && NULL == node->right) 28 { 29 tail->next = (struct Leaf *)malloc(sizeof(struct Leaf)); 30 tail->next->id = id; 31 tail->next->level = level; 32 tail->next->next = NULL; 33 tail->next->pre = tail; 34 tail->next->node = node; 35 tail = tail->next; 36 return tail; 37 } 38 tail = findleaf(node->left, tail, level + 1, id * 2); 39 tail = findleaf(node->right, tail, level + 1, id * 2 + 1); 40 return tail; 41 } 42 43 //获取叶子节点链表,head节点不存叶子,head的前驱节点为tail 44 struct Leaf* GetLeaf(struct Node* node) 45 { 46 struct Leaf* head = (struct Leaf *)malloc(sizeof(struct Leaf)); 47 head->node = NULL; 48 head->next = NULL; 49 head->pre = NULL; 50 head->pre = findleaf(node, head, 1, 1); 51 return head; 52 } 53 54 //采用归并的方法找最远距离两个点,left和right为叶子双向链表的左右边界,maxdis指向当前搜索到的最大距离, 55 //level指当前递归第几层,maxlevel为叶子节点的最大层次 56 struct Node** GetPoints(struct Leaf* left, struct Leaf* right,unsigned int *maxdis, unsigned long level, unsigned long maxlevel) 57 { 58 unsigned long pivot, leftMaxLevel = 0, rightMaxLevel = 0; 59 struct Leaf* mid = left, *temp; 60 struct Node* res[2]; 61 struct Node** ret = NULL, **tmp; 62 if (level > maxlevel || left == right) 63 return NULL; 64 //找出在第level层,左右半部叶子分割点mid 65 pivot = 1 << (maxlevel - level - 1); 66 while (right->next != mid) 67 { 68 if (pivot & (mid->id << (maxlevel - mid->level))) 69 break; 70 mid = mid->next; 71 } 72 //mid不在left和right的边界 73 if (mid != left && mid != right->next) 74 { 75 //找出左半部叶子最大层次深度 76 temp = left; 77 while (temp != mid) 78 { 79 if (leftMaxLevel < temp->level) 80 { 81 leftMaxLevel = temp->level; 82 res[0] = temp->node; 83 } 84 temp = temp->next; 85 } 86 //找出右半部叶子最大层次深度 87 temp = mid; 88 while (temp != right->next) 89 { 90 if (rightMaxLevel < temp->level) 91 { 92 rightMaxLevel = temp->level; 93 res[1] = temp->node; 94 } 95 temp = temp->next; 96 } 97 //找到更大距离,保存起来 98 if (*maxdis < (leftMaxLevel - level + rightMaxLevel - level)) 99 { 100 *maxdis = leftMaxLevel - level + rightMaxLevel - level; 101 ret = res; 102 } 103 //减少距离较近的叶子做无谓的比较,直接返回 104 if (*maxdis >((maxlevel - level - 1) * 2)) 105 { 106 return ret; 107 } 108 tmp = GetPoints(left, mid->pre, maxdis, level + 1, maxlevel); 109 if (NULL != tmp) 110 { 111 ret = tmp; 112 } 113 tmp = GetPoints(mid, right, maxdis, level + 1, maxlevel); 114 if (NULL != tmp) 115 { 116 ret = tmp; 117 } 118 } 119 else if (mid == left) 120 { 121 if (*maxdis >((maxlevel - level - 1) * 2)) 122 { 123 return ret; 124 } 125 ret = GetPoints(left, right, maxdis, level + 1, maxlevel); 126 } 127 else if (mid == right->next) 128 { 129 if (*maxdis >((maxlevel - level - 1) * 2)) 130 { 131 return ret; 132 } 133 ret = GetPoints(left, right, maxdis, level + 1, maxlevel); 134 } 135 return ret; 136 } 137 138 void findPoints(struct Node* node, unsigned int *maxdis, struct Node** left, struct Node** right) 139 { 140 unsigned long maxLevel = 0; 141 struct Node** ret; 142 struct Leaf* head = GetLeaf(node), *temp; 143 temp = head->next; 144 //找出叶子最大深度 145 while (temp != NULL) 146 { 147 if (maxLevel < temp->level) 148 maxLevel = temp->level; 149 temp = temp->next; 150 } 151 ret = GetPoints(head->next, head->pre, maxdis, 1, maxLevel); 152 *left = ret[0]; 153 *right = ret[1]; 154 } 155 156 #if 0 157 //找出两个叶子节点共同祖先编号 158 int findAncestor(int m, int n) 159 { 160 while (m > 0 && n > 0) 161 { 162 while (m > n && m != 1) 163 m = m / 2; 164 if (m == n) 165 return m; 166 while (m < n && n != 1) 167 n = n / 2; 168 if (m == n) 169 return m; 170 } 171 } 172 173 //找出两个叶子节点距离 174 int findDistance(int m, int n) 175 { 176 int d = 0, anc; 177 anc = findAncestor(m, n); 178 while (m != anc) 179 { 180 m = m / 2; 181 d++; 182 } 183 while (n != anc) 184 { 185 n = n / 2; 186 d++; 187 } 188 return d; 189 } 190 191 struct Node** findPoints(struct Node* node) 192 { 193 int max = 0, dis = 0; 194 struct Node* points[2]; 195 struct Leaf* p, *q; 196 struct Leaf* head = GetLeaf(node); 197 p = head->next; 198 //简单的遍历叶子链表,计算两两间距离 199 while (p->next != NULL) 200 { 201 q = p->next; 202 do{ 203 dis = findDistance(p->id, q->id); 204 if (max < dis) 205 { 206 points[0] = p->node; 207 points[1] = q->node; 208 max = dis; 209 } 210 q = q->next; 211 } while (q != NULL); 212 p = p->next; 213 } 214 return points; 215 } 216 #endif 217 218 int main() 219 { 220 unsigned int maxdis = 0; 221 struct Node* l, *r = NULL; 222 struct Node* h = new Node(1); 223 h->left = new Node(2); 224 h->right = new Node(3); 225 h->right->left = new Node(6); 226 h->right->right = new Node(7); 227 h->right->left->left = new Node(12); 228 h->right->left->right = new Node(13); 229 h->right->right->left = new Node(14); 230 h->right->right->right = new Node(15); 231 h->right->left->left->left = new Node(24); 232 h->right->right->right->right = new Node(31); 233 findPoints(h, &maxdis, &l, &r); 234 cout << l->data << endl; 235 cout << r->data << endl; 236 while (1); 237 }