二叉樹中兩個節點的最近公共祖先節點方法全集
阿新 • • 發佈:2019-02-17
一.如果資料結構為三叉連結串列,即含有指向父節點的指標:
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;
}
}
}
以上方法叫雙重迴圈法,上面的演算法實際上是將一個結點回退到父結點,每退一步,另一個結點指標將回退到不能退為止。此過程來判斷它們兩結點是否有共同的父母。
檢查當前節點;如果value1和value2都小於當前節點的值,檢查它的左子節點;如果value1和value2都大於當前節點的值,檢查它的右子節點;否則,當前節點就是最近共同祖先。
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裡有沒有此節點,有則找到所以的祖先節點,沒有就繼續找)