求二叉树最远距离两个点

思路跟前面大体一样,先找出叶子节点的链表。这次增加叶子层次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 }

 

posted @ 2016-02-23 22:01  zhou09  阅读(689)  评论(0编辑  收藏  举报