求树中最低的公共祖先
和二叉树中两个结点的公共祖先相关的有两个问题,一个是求最低的公共祖先,第二个是求所有公共祖先。
首先看第一个,仔细观察不难发现,二叉树中两个结点的最低公共祖先满足一个性质,就是给定两个结点分别处于以最低公共祖先两个孩子为根节点的子树中。我们可以采用DFS来搜索两个给定结点,对于每个结点通过比较搜索其两子树的返回值和来确定,因为是先搜索两子树后判定,所以遇到的第一个符合条件的结点一定是最低公共祖先。
代码如下:
1 PtrNode lowest_common_ancestor(PtrNode root, int a, int b) 2 { 3 PtrNode res, res_l, res_r; 4 if (root == NULL) { 5 res = NULL; 6 } 7 else { 8 if (root->value == a || root->value == b) { 9 res = root; 10 } 11 else { 12 res_l = lowest_common_ancestor(root->lchild, a, b); 13 res_r = lowest_common_ancestor(root->rchild, a, b); 14 if (res_l != NULL && res_r != NULL) { 15 res = root; 16 } 17 else { 18 res = res_l != NULL ? res_l : res_r; 19 } 20 } 21 } 22 return res; 23 }
对于第二个问题,思路是一样的,由于祖先之间是存在父子关系的,当后序遍历到某个结点时如果其中一个儿子是两个结点的祖先,那么当前结点也是公共祖先。代码如下:
1 int print_all_common_ancestor(PtrNode root, int a, int b) 2 { 3 int res_l, res_r, res; 4 if (root == NULL) { 5 res = 0; 6 } 7 else { 8 res_l = print_all_common_ancestor(root->lchild, a, b); 9 res_r = print_all_common_ancestor(root->rchild, a, b); 10 if (root->value == a || root->value == b) { 11 if (res_l == 1 || res_r == 1) { 12 printf("%d\n", root->value); 13 res = 2; 14 } 15 else { 16 res = 1; 17 } 18 } 19 else { 20 if ((res_l == 1 && res_r == 1) || (res_l == 2) || (res_r == 2)) { 21 printf("%d\n", root->value); 22 res = 2; 23 } 24 else if (res_l == 1 || res_r == 1){ 25 res = 1; 26 } 27 else{ 28 res = 0; 29 } 30 } 31 } 32 return res; 33 }