1)分别记录从根结点到两个结点的路径,两条路径的最后一个公共结点就是所求。
bool cal(Node *node, char *str, char ch, int &len){
if(node == NULL){
return false;
}
str[len++] = node->key;
if(node->key == ch)
return true;
if(cal(node->lchild, str, ch, len))
return true;
if(node->lchild) len--; // !!! 只有有孩子的时候才能回退长度,羞死
if(cal(node->rchild, str, ch, len))
return true;
if(node->rchild) len--; // !!!
return false;
}
char find_common_father1(Node *root, char x, char y){
if(root == NULL)
return '-';
char strx[100], stry[100];
int lena = 0, lenb = 0;
bool f1 = cal(root, strx, x, lena);
bool f2 = cal(root, stry, y, lenb);
if(f1 == false || f2 == false)
return '-';
int i, j;
for(i = lena-1; i >= 0; i--){
bool flag = false;
for(j = lenb-1; j >= 0; j--)
if(strx[i] == stry[j]){
flag = true;
break;
}
if(flag) break;
}
return strx[i];
}
1、当前结点的值跟给出的两个结点的值的其中一个相同,返回当前结点;
2、给出的两个结点的其中一个在当前结点左子树,另一个在当前结点右子树,返回当前结点
3、两个结点都在左子树,返回左子树查找的结果
4、两个结点都在右子树,返回右子树查找的结果
Node *search(Node *root, char x, char y){
if(root == NULL)
return NULL;
if(root->key == x || root->key == y)
return root;
Node *f1 = search(root->lchild, x, y);
Node *f2 = search(root->rchild, x, y);
if(f1 && f2)
return root;
if(f1)
return f1;
if(f2)
return f2;
return NULL;
}
char find_common_father2(Node *root, char x, char y){
Node *ans = search(root, x, y);
return ans->key;
}
完整示例:
#include
#include
#include
#include
#include
using namespace std;
typedef struct NODE{
NODE()
:key('0'), lchild(NULL), rchild(NULL){}
char key;
NODE *lchild;
NODE *rchild;
} Node;
// 给出先序和中序,重建二叉树
void pre_mid(Node *&node, int len, char *pre, char *mid){
if(len <= 0) return;
node = new Node();
node->key = *pre;
char *pm = strchr(mid, *pre);
int l_len = pm - mid;
int r_len = len - l_len - 1;
pre_mid(node->lchild, l_len, pre+1, mid);
pre_mid(node->rchild, r_len, pre+l_len+1, pm+1);
}
bool cal(Node *node, char *str, char ch, int &len){
if(node == NULL){
return false;
}
str[len++] = node->key;
if(node->key == ch)
return true;
if(cal(node->lchild, str, ch, len))
return true;
if(node->lchild) len--; // !!! 只有有孩子的时候才能回退长度,羞死
if(cal(node->rchild, str, ch, len))
return true;
if(node->rchild) len--; // !!!
return false;
}
char find_common_father1(Node *root, char x, char y){
if(root == NULL)
return '-';
char strx[100], stry[100];
int lena = 0, lenb = 0;
bool f1 = cal(root, strx, x, lena);
bool f2 = cal(root, stry, y, lenb);
if(f1 == false || f2 == false)
return '-';
int i, j;
for(i = lena-1; i >= 0; i--){
bool flag = false;
for(j = lenb-1; j >= 0; j--)
if(strx[i] == stry[j]){
flag = true;
break;
}
if(flag) break;
}
return strx[i];
}
Node *search(Node *root, char x, char y){
if(root == NULL)
return NULL;
if(root->key == x || root->key == y)
return root;
Node *f1 = search(root->lchild, x, y);
Node *f2 = search(root->rchild, x, y);
if(f1 && f2)
return root;
if(f1)
return f1;
if(f2)
return f2;
return NULL;
}
char find_common_father2(Node *root, char x, char y){
Node *ans = search(root, x, y);
return ans->key;
}
void free_tree(Node *node){
if(node == NULL)
return;
free_tree(node->lchild);
free_tree(node->rchild);
free(node);
}
int main()
{
Node *root = NULL;
char *pre = "DBACEGF";
char *mid = "ABCDEFG";
pre_mid(root, strlen(pre), pre, mid);
printf("%c\n", find_common_father1(root, 'E', 'F'));
printf("%c\n", find_common_father2(root, 'A', 'C'));
free_tree(root);
return 0;
}