计算二叉树中两个节点的距离
问题
对于普通的二叉树,如何找到两个给定节点之家的距离?距离是指连接两个节点需要的最小的边的条数。
例如下面的二叉树:
这个问题很全面的考察了二叉树相关的知识,建议大家先尝试自己解决~
分析
假设给定的节点为node1, node2,可以分为下面两种情况:
1) node1是node2的祖先节点或孩子节点,可以理解为两个节点在一条线上。 例如:Dist(2,4), Dist(6,1)
2) node1 和 node2 没有直接或间接的父子关系。 例如,Dist(4,3), 他们需要一个共同的祖先节点1 连接起来。
关于两个节点的最低公共祖先(LCA)问题,可以参考我之前的文章(文章分类:数据结构)
通过观察可以总结出下面的公式, lca是两个节点的最低公共祖先节点:
Dist(n1, n2) = Dist(root, n1) + Dist(root, n2) - 2*Dist(root, lca)
这个公式已经含盖了上面的两种情况。先找出lca,再求root节点到某个节点的距离就比较简单了。
以下是C++代码:
1 #include <iostream>
2 #include <cstdlib>
3 #include <cstdio>
4 using namespace std;
5
6 typedef struct node{
7 int val;
8 node *lchild;
9 node *rchild;
10 node(int x) : val(x), lchild(NULL), rchild(NULL) {}
11 }Node;
12
13 //计算节点值为n到根节点的距离,-1表示没有在root树下找到
14 int findlevel(Node *root, int n){
15 if(root == NULL)
16 return -1;
17 if(root->val == n)
18 return 0;
19 //先在左子树中查找
20 int level = findlevel(root->lchild, n);
21 //左子树中没有找到则到右子树中查找
22 if(level == -1)
23 level = findlevel(root->rchild, n);
24 if(level != -1)
25 return level+1;
26 return -1;
27 }
28
29 //找两个节点的最近公共祖先
30 Node *findLCA(Node *root, int n1, int n2){
31 if(root == NULL)
32 return NULL;
33 //找到两个节点中的一个就返回
34 if((root->val == n1) || (root->val == n2))
35 return root;
36 //分别在左右子树查找两个节点
37 Node *l = findLCA(root->lchild, n1, n2);
38 Node *r = findLCA(root->rchild, n1, n2);
39 if((l != NULL) && (r != NULL))
40 //此时说明,两个节点分别在左右子树中,当前节点就是LCA
41 return root;
42 return ((l == NULL) ? r : l);
43
44 }
45
46 //计算两个节点的距离
47 int distance(Node *root, int n1, int n2){
48 Node *lca = findLCA(root, n1, n2);
49 int dis_lca = findlevel(root, lca->val);
50 int dis_n1 = findlevel(root, n1);
51 int dis_n2 = findlevel(root, n2);
52 //cout << dis_lca << dis_n1 << dis_n2 << endl;
53 int ans = dis_n1 + dis_n2 - 2 * dis_lca;
54 return ans;
55 }
56
57 //前序遍历
58 void travel(Node *root){
59 if(root == NULL)
60 return;
61 cout << root->val;
62 travel(root->lchild);
63 travel(root->rchild);
64 }
65
66 int main(){
67 Node *root = new Node(1);
68 root->lchild = new Node(2);
69 root->rchild = new Node(3);
70 root->lchild->lchild = new Node(4);
71 root->lchild->rchild = new Node(5);
72 root->rchild->lchild = new Node(6);
73 root->rchild->rchild = new Node(7);
74 root->rchild->lchild->rchild = new Node(8);
75 travel(root);
76 cout << endl;
77 cout << "dis(4,5) = " << distance(root, 4, 5) << endl;
78 cout << "dis(4,6) = " << distance(root, 4, 6) << endl;
79 cout << "dis(3,4) = " << distance(root, 3, 4) << endl;
80 cout << "dis(2,4) = " << distance(root, 2, 4) << endl;
81 cout << "dis(8,5) = " << distance(root,