劍指Offer 面試題18 樹的子結構

2021-06-25 12:39:49 字數 4216 閱讀 7865

/*

樹的子結構:

輸入兩顆二叉樹a和b,判斷b是不是a的子結構。

例如:樹a:                        樹b

8                            8

87                  9          292

47過程總結:

在樹a中查詢與樹b中根節點一樣的值,然後遞迴比較兩者的左子樹和右子樹是否相同

遞迴出口是:樹b的左右子樹為空

這道題目有兩個遞迴:

主遞迴:用於確定樹a中的那個根節點與樹b的根節點進行比較,一旦相同,呼叫子遞迴

子遞迴:用於判斷兩個樹中是否具有相同的子結構。這裡注意:如果小樹先遞迴到空,說明是有子結構的。

如果兩個根節點(前根遍歷)都不同或者大樹已經為空,肯定不是。如果根節點相同,那麼分別遍歷:

大樹與小樹的左子樹 與 大樹與小數的右子樹 是否都具有子結構

輸入:輸入可能包含多個測試樣例,輸入以eof結束。

對於每個測試案例,輸入的第一行乙個整數n,m(1<=n<=1000,1<=m<=1000):n代表將要輸入的二叉樹a的節點個數(節點從1開始計數),m代表將要輸入的二叉樹b的節點個數(節點從1開始計數)。接下來一行有n個數,每個數代表a樹中第i個元素的數值,接下來有n行,第乙個數ki代表第i個節點的子孩子個數,接下來有ki個樹,代表節點i子孩子節點標號。接下來m+1行,與樹a描述相同。

輸出:對應每個測試案例,

若b是a的子樹輸出」yes」(不包含引號)。否則,輸出「no」(不包含引號)。

樣例輸入:

7 38 8 7 9 2 4 7

2 2 3

2 4 500

2 6 700

8 9 2

2 2 300

1 1203

0樣例輸出:

yesno

*//*

關鍵:1

if(psmallhead2 == null)//易錯,這裡小樹為空必須放在前面,否則會出現大樹也為空,但大樹放在前面返回為假的情況

if(pbighead1 == null)//遞迴出口

2return judgesubtree(pbighead1->_left,psmallhead2->_left) && judgesubtree(pbighead1->_right,psmallhead2->_right);//兩個根節點值相等,就返回左右子樹的判定情況

3if(pbighead1->_ival == psmallhead2->_ival)//如果頭結點對應的值相同,則進行遞迴

if(!bres)//這裡,如果左子樹如果找到,後面右子樹就不需要查詢了,因此需要加判定條件

*/#include

#include

const int maxsize = 1001;//1000個節點

typedef struct treenode

treenode;

treenode nodearr1[maxsize];

treenode nodearr2[maxsize];

int _iindex1;

int _iindex2;

treenode* createnode1()

treenode* createnode2()

//建大樹

void buildbigtree(treenode** phead,int* parr,int n,treenode* (*pfun)())//如果剛開始就穿入的是空指標

for(int i = 0 ; i < n ; i++)//先把各個單獨的節點建立起來,其中首節點不需要建立,因為已經建立了

else//對於頭結點賦值

}//接下來構建二叉樹的指向問題,共有n行,代表n個節點

for(int j = 1 ; j <= n; j++)

else if(inum == 1)//如果只有乙個節點,預設為子節點編號左節點

else if(inum == 2)//構建該節點的左右子節點}}

//建小樹

void buildsmalltree(treenode** phead,int* parr,int n,treenode* (*pfun)())

for(int i = 0 ; i < n ; i++)//先把各個單獨的節點建立起來,其中首節點不需要建立,因為已經建立了

else//對於頭結點賦值

}//接下來構建二叉樹的指向問題,共有n行,代表n個節點

for(int j = 1 ; j <= n; j++)

else if(inum == 1)//如果只有乙個節點,預設為子節點編號左節點

else if(inum == 2)//構建該節點的左右子節點}}

//主遞迴函式:設定頭結點,對於頭結點相同比較,一旦發現兩者從頭結點向下遍歷。

//判斷是否具有相同子結構的次遞迴函式:若發現頭結點的值不同,則立即返回。否則返回左子樹的比較情況和右子樹

//的比較情況。一旦小樹變空,說明是正確的。大數變空則是錯誤的。(遞迴出口)

//因為這裡是遍歷,因此不需要用二級指標。只有當需要改變的時候採用二級指標

bool judgesubtree1(treenode* pbighead1,treenode* psmallhead2)

if(pbighead1 == null)//遞迴出口

if(pbighead1->_ival == psmallhead2->_ival)//兩個根節點值相等,就返回左右子樹的判定情況

else

}bool judgesubtree(treenode* pbighead1,treenode* psmallhead2)

if(pbighead1 == null)//遞迴出口

if(pbighead1->_ival != psmallhead2->_ival)

return judgesubtree(pbighead1->_left,psmallhead2->_left) && judgesubtree(pbighead1->_right,psmallhead2->_right);//兩個根節點值相等,就返回左右子樹的判定情況

}bool issubtree1(treenode* pbighead1,treenode* psmallhead2)

bool bres = false;//預設為假

if(pbighead1->_ival == psmallhead2->_ival)//如果頭結點對應的值相同,則進行遞迴

if(!bres)//這裡,如果左子樹如果找到,後面右子樹就不需要查詢了,因此需要加判定條件

}return bres;

}bool issubtree(treenode* pbighead1,treenode* psmallhead2)

if(!bres)//這裡,如果左子樹如果找到,後面右子樹就不需要查詢了,因此需要加判定條件}}

return bres;

}void process()

//建大樹

int iarr1[maxsize];

_iindex1 = 0;//注意結點編號從1開始,注意記錄頭結點

memset(nodearr1,null,sizeof(nodearr1));

treenode* head1 = createnode1();//不能穿入空指標

treenode** phead1 = &head1;

for(int i = 0 ; i < n ; i++)//接受樹a的n各節點的值,這裡應該順便將各個節點建立出來

buildbigtree(phead1,iarr1,n,createnode1);

//建小樹

int iarr2[maxsize];

_iindex2 = 0;//注意結點編號從1開始,注意記錄頭結點

memset(nodearr2,null,sizeof(nodearr2));

treenode* head2 = createnode2();//不能穿入空指標

treenode** phead2 = &head2;

for(int j = 0 ; j < m ; j++)//接受樹a的n各節點的值,這裡應該順便將各個節點建立出來

buildsmalltree(phead2,iarr2,m,createnode2);

//對已經建立的樹,判斷大樹是否包含小樹的子結構

bool bres = issubtree(head1,head2);

if(bres)

else}}

int main(int argc,char* argv)

劍指Offer 面試題18 樹的子結構

輸入兩棵二叉樹a,b,判斷b是不是a的子結構。ps 我們約定空樹不是任意乙個樹的子結構 分析 這裡說的子結構不是子樹,只是根據值來判斷,更像是 包含 關係吧。首先需要在a樹中找到和b根節點值一樣的結點,然後判斷a的子樹和b是否結構和值相同。在a中找到和b的根結點值相同的操作等同於二叉樹遍歷,用先序遍...

劍指offer 面試題26 樹的子結構

完整 位址 輸入兩棵二叉樹a,b,判斷b是不是a的子結構。ps 我們約定空樹不是任意乙個樹的子結構 找到樹a中與樹b根節點值相同的節點,設樹a中該節點為subroot 在遍歷樹b的同時,遍歷subroot,如果遍歷完樹b發現subroot中沒有與b不一致的地方,則b是a的子結構 遍歷樹b時,發現su...

劍指offer 面試題26 樹的子結構

輸入兩棵二叉樹a和b,判斷b是不是a的子結構。約定空樹不是任意乙個樹的子結構 b是a的子結構,即 a中有出現和b相同的結構和節點值。例如 給定的樹 a 3 4 5 1 2 給定的樹 b 4 1返回 true,因為 b 與 a 的乙個子樹擁有相同的結構和節點值。示例 1 輸入 a 1,2,3 b 3,...