您的位置:首页 > 其它

二叉树中两个节点的最近公共祖先节点方法全集

2016-06-15 21:28 381 查看
一.如果数据结构为三叉链表,即含有指向父节点的指针:

Node * NearestCommonAncestor(Node * root,Node * p,Node * q)

{

Node * temp;

while(p!=NULL)

{

p=p->parent;

temp=q;

while(temp!=NULL)

{

if(p==temp->parent)

return p;

temp=temp->parent;

}

}

}


以上方法叫双重循环法,上面的算法实际上是将一个结点回退到父结点,每退一步,另一个结点指针将回退到不能退为止。此过程来判断它们两结点是否有共同的父母。



二.如果为二叉搜索树中找出两节点的最近祖先节点
[b]检查当前节点;如果value1和value2都小于当前节点的值,检查它的左子节点;如果value1和value2都大于当前节点的值,检查它的右子节点;否则,当前节点就是最近共同祖先。

[/b]

Node* findLowerstCommonAncestor(Node* root, int value1, int value2)
{
while ( root != NULL )
{
int value = root->getValue();
if ( value > value1 && value > value2 )
root = root->getLeft();
else if (value < value1 && value < value2)
root = root->getRight();
else
return root;
}
return NULL;
}


三.如果是普通二叉树
bool Getpath(BinaryTreeNode<int>* root,BinaryTreeNode<int>* str1,
list<BinaryTreeNode<int>*>& List)    //寻找路径
{
if(root == NULL || str1 == NULL)  //如果其中的一个为空,便不成立
return false;
if(root == str1)    //如果第一个就是,并且与跟节点相同,便返回
{
List.push_back(root);
return true;
}

List.push_back(root);//先压左
bool juge = Getpath(root->_left,str1,List);

if(!juge)  //在左不成立的情况下,才压右
juge = Getpath(root->_right,str1,List);

if(!juge)    //把不成立的数据弹出
List.pop_back();

return juge;
}

BinaryTreeNode<int>* CommonAncestor(BinaryTreeNode<int>* root,BinaryTreeNode<int>* str1,
BinaryTreeNode<int>* str2)
{
assert(root);
assert(str1);
assert(str2);   //断言,确保传值
if(root == NULL || str1 == NULL || str2 ==NULL)  //判断条件是否成立
return NULL;

if(root == str1 || root == str2)  //如果根节点等于其中的一个,便说明,没有公共祖先节点
return NULL;

list<BinaryTreeNode<int>*> List1;
list<BinaryTreeNode<int>*> List2;
bool juge1 = Getpath(root,str1,List1);
bool juge2 = Getpath(root,str2,List2);

if(juge1 == false || juge2  == false)
return NULL;
BinaryTreeNode<int> * commonParent=NULL;
list<BinaryTreeNode<int>*>::iterator ite1=List1.begin();
list<BinaryTreeNode<int>*>::iterator ite2=List2.begin();
for(;ite1!=List1.end() && ite2!=List2.end();ite1++,ite2++)  //寻找最近公共节点
{
if(*ite1==*ite2)
commonParent=*ite1;
else
break;
}
return commonParent;
}
此处借用了队列的用法,把到两个节点的路径分别加入到两个队列中,因为都是从根向下遍历,开始节点都是相同的,所以,最后一次相同的节点,就是距离他们最近的公共节点。

思想

活用Hash表:

如果每个节点有指向父节点的指针,那么逆向遍历两个节点的所有祖先节点,找第一个一样的祖先,可用hash表存储,

时间复杂度是树的深度,空间复杂度也是数的深度。

可以将q到头结点建立一张Hash表,然后从p到头结点,边遍历边查找Hash表,直到第一次在hash表在哦个查找到节点值存在。

(其实我们可以简单的过程来看思想二的算法:我们可以开辟指向节点的指针数组,先从一个节点下手,让它一直回退,每退一步,数组新的位置记录下它,即指向该节点,直到第一个节点回退完,再进行第二个节点的回退,每退一步就检查一下它在数组中有没有,这样和思想一是一样的,故为了加速,这里应该将每一个节点的回退过程的地址扔进hashset里去,在回退第二个节点时,查一下hashset里有没有此节点,有则找到所以的祖先节点,没有就继续找)

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: