判斷一顆二叉樹是不是另一棵二叉樹的子結構
1、題目描述:
如何判斷一個二叉樹是否是另一個的子結構?
比如:
2
/ \
9 8
/ \ /
2 3 5
/
6
有個子結構是
9
/ \
2 3
2、分析問題:
有關二叉樹的演算法問題,一般都可以通過遞迴來解決。那麼寫成一個正確的遞迴程式,首先一定要分析正確遞迴結束的條件。
拿這道題來講,什麼時候遞迴結束。
<1>第二個二叉樹root2為空白時,說明root2是第一棵二叉樹的root1的子結構,返回true。
<2>當root1為空白時,此時root2還沒為空白,說明root2不是root1的子結構,返回false。
<3>遞迴下面有兩種思路:
方法一:現在root1中找結點值與root2的值相等的結點,如果找到就判斷root2是不是這個結點開頭的子結構。所以,首先IsSubTree()判斷。
方法二:就是直接判斷,相同就遞迴判斷root2左右子樹是不是也是相應的子結構。如果值不相同,就分別遞迴到root1的左右子樹尋找。尤其要注意最後兩句遞迴的邏輯判斷。
3、代碼:
方法一:
//判斷root2是不是root1開頭的子結構
boolIsSubTree(BiTreeNode *root1,BiTreeNode *root2)
{
//先判斷root2
if(root2==NULL)
return true;
if(root1==NULL)
return false;
if(root1->data!=root2->data)
return false;
returnIsSubTree(root1->LC,root2->LC) &&IsSubTree(root1->RC,root2->RC);
}
//遞迴尋找以root1為節點的樹中,是否有和root2相同的值,如果有,則調用IsSubTree(root1, root2);
boolCheckIfSubTree(BiTreeNode *root1,BiTreeNode *root2)
{
if(root1==NULL)
return false;
bool result=false;
if(root1->data==root2->data)
result=IsSubTree(root1,root2);
if(result==false)
result=CheckIfSubTree(root1->LC,root2);
if(result==false)
result=CheckIfSubTree(root1->RC,root2);
return result;
}
方法二:
//一次遞迴完成
boolCheckIfSubTree2(BiTreeNode *root1,BiTreeNode *root2)
{
if(root2==NULL)
return true;
if(root1==NULL)
return false;
if(root1->data==root2->data)
returnCheckIfSubTree2(root1->LC,root2->LC) &&CheckIfSubTree2(root1->RC,root2->RC);
else
returnCheckIfSubTree2(root1->LC,root2) || CheckIfSubTree2(root1->RC,root2);
}
4、附先序產生二叉樹的代碼
struct BiTreeNode
{
struct BiTreeNode* LC;
struct BiTreeNode* RC;
int data;
};
void CreateBiTree(BiTreeNode* &root)
{
int ch;
cin>>ch;
if(ch==0)
{
root=NULL;
}
else
{
root=(BiTreeNode*)malloc(sizeof(BiTreeNode));
if(root==NULL)
exit(1);
root->data=ch;
//cout<<"--"<<root->data<<endl;
CreateBiTree(root->LC);
CreateBiTree(root->RC);
}
}
5、小結
一定要好好的體會遞迴,尤其是遞迴結束的情況。這是解大多數遞迴問題的關鍵。
本代碼已在VC++6.0調試通過,歡迎大家提出問題。