通过上一篇的博客我们知道,可以利用栈来实现二叉树的后序遍历。其实这里有一个性质,就是当使用非递归后序遍历时,栈中的元素就是当前节点到根节点的路径。利用这个规律,我们就可以求解最近公共最先问题了。
算法
找出两个节点各自到根节点的路径。这里利用非递归后序遍历二叉树,既可以找到两个节点到根节点的路径。根据路径找出最近的公共祖先。首先根节点肯定是他们的祖先,可以从跟节点开始查找,直到最后一个相同的树节点,就是他们的公共祖先了。
实现
void BiTree::ancestor(
char A,
char B){
vector<BiNode *> pathA,pathB;
BiNode *p,*r;
r = NULL;
p = root;
stack<BiNode*> my_stack;
int pathCnt=
0;
while(p!=NULL || !my_stack.empty()){
if(p){
my_stack.push(p);
p=p->lchild;
}
else{
p=my_stack.top();
if(p->rchild!=NULL && p->rchild!=r){
p=p->rchild;
my_stack.push(p);
p=p->lchild;
}
else{
p=my_stack.top();
my_stack.pop();
if(p->data==A){
cout<<
"找到"<<A<<
"的路径:"<<endl;
pathA.push_back(p);
while(!my_stack.empty()){
p=my_stack.top();
my_stack.pop();
pathA.push_back(p);
}
for(
int i=pathA.size()-
1;i>=
0;i--){
cout<<pathA[i]->data<<
' ';
my_stack.push(pathA[i]);
p=pathA[i];
}
p=my_stack.top();
my_stack.pop();
cout<<endl;
++pathCnt;
}
if(p->data==B){
cout<<
"找到"<<B<<
"的路径:"<<endl;
pathB.push_back(p);
while(!my_stack.empty()){
p=my_stack.top();
my_stack.pop();
pathB.push_back(p);
}
for(
int i=pathB.size()-
1;i>=
0;i--){
cout<<pathB[i]->data<<
' ';
my_stack.push(pathB[i]);
p=pathB[i];
}
p=my_stack.top();
my_stack.pop();
cout<<endl;
++pathCnt;
}
if(pathCnt==
2)
break;
r=p;
p=NULL;
}
}
}
BiNode *common_node;
int i,j;
i=pathA.size()-
1;
j=pathB.size()-
1;
while(i>=
0 && j>=
0 && pathA[i]==pathB[j]){
common_node = pathA[i];
--i,--j;
}
cout<<
"结点"<<A<<
"和节点"<<B<<
"的最近公共祖先是"<<common_node->data<<
"。"<<endl;
}
测试
#include <iostream>
#include "BiTree.h"
using namespace std;
int main()
{
BiTree a;
string s;
s=
"ABD##E#F##C##";
a.createBiTree(s);
a.ancestor(
'D',
'D');
cout<<
"--------------------"<<endl;
a.ancestor(
'D',
'F');
cout<<
"--------------------"<<endl;
a.ancestor(
'D',
'C');
cout<<
"--------------------"<<endl;
return 0;
}