一文搞定面試中的二叉樹(shù)問(wèn)題
版權(quán)所有,轉(zhuǎn)載請(qǐng)注明出處,謝謝!
http://blog.csdn.net/walkinginthewind/article/details/7518888
樹(shù)是一種比較重要的數(shù)據(jù)結(jié)構(gòu),尤其是二叉樹(shù)。二叉樹(shù)是一種特殊的樹(shù),在二叉樹(shù)中每個(gè)節(jié)點(diǎn)最多有兩個(gè)子節(jié)點(diǎn),一般稱(chēng)為左子節(jié)點(diǎn)和右子節(jié)點(diǎn)(或左孩子和右孩子),并且二叉樹(shù)的子樹(shù)有左右之分,其次序不能任意顛倒。二叉樹(shù)是遞歸定義的,因此,與二叉樹(shù)有關(guān)的題目基本都可以用遞歸思想解決,當(dāng)然有些題目非遞歸解法也應(yīng)該掌握,如非遞歸遍歷節(jié)點(diǎn)等等。本文努力對(duì)二叉樹(shù)相關(guān)題目做一個(gè)較全的整理總結(jié),希望對(duì)找工作的同學(xué)有所幫助。
二叉樹(shù)節(jié)點(diǎn)定義如下:
struct BinaryTreeNode
{
? ? int m_nValue;
? ? BinaryTreeNode* m_pLeft;
? ? BinaryTreeNode* m_pRight;
};
相關(guān)鏈接:
輕松搞定面試中的鏈表題目
題目列表:
1. 求二叉樹(shù)中的節(jié)點(diǎn)個(gè)數(shù)
2. 求二叉樹(shù)的深度
3. 前序遍歷,中序遍歷,后序遍歷
4.分層遍歷二叉樹(shù)(按層次從上往下,從左往右)
5. 將二叉查找樹(shù)變?yōu)橛行虻碾p向鏈表
6. 求二叉樹(shù)第K層的節(jié)點(diǎn)個(gè)數(shù)
7. 求二叉樹(shù)中葉子節(jié)點(diǎn)的個(gè)數(shù)
8. 判斷兩棵二叉樹(shù)是否結(jié)構(gòu)相同
9. 判斷二叉樹(shù)是不是平衡二叉樹(shù)
10. 求二叉樹(shù)的鏡像
11. 求二叉樹(shù)中兩個(gè)節(jié)點(diǎn)的最低公共祖先節(jié)點(diǎn)
12. 求二叉樹(shù)中節(jié)點(diǎn)的最大距離
13. 由前序遍歷序列和中序遍歷序列重建二叉樹(shù)
14.判斷二叉樹(shù)是不是完全二叉樹(shù)
詳細(xì)解答
1. 求二叉樹(shù)中的節(jié)點(diǎn)個(gè)數(shù)
遞歸解法:
(1)如果二叉樹(shù)為空,節(jié)點(diǎn)個(gè)數(shù)為0
(2)如果二叉樹(shù)不為空,二叉樹(shù)節(jié)點(diǎn)個(gè)數(shù) = 左子樹(shù)節(jié)點(diǎn)個(gè)數(shù) + 右子樹(shù)節(jié)點(diǎn)個(gè)數(shù) + 1
參考代碼如下:
[cpp]?view plaincopy
int?GetNodeNum(BinaryTreeNode?*?pRoot)?? {?? ????if(pRoot?==?NULL)??? ????????return?0;?? ????return?GetNodeNum(pRoot->m_pLeft)?+?GetNodeNum(pRoot->m_pRight)?+?1;?? }??
2. 求二叉樹(shù)的深度
遞歸解法:
(1)如果二叉樹(shù)為空,二叉樹(shù)的深度為0
(2)如果二叉樹(shù)不為空,二叉樹(shù)的深度 = max(左子樹(shù)深度, 右子樹(shù)深度) + 1
參考代碼如下:
[cpp]?view plaincopy
int?GetDepth(BinaryTreeNode?*?pRoot)?? {?? ????if(pRoot?==?NULL)??? ????????return?0;?? ????int?depthLeft?=?GetDepth(pRoot->m_pLeft);?? ????int?depthRight?=?GetDepth(pRoot->m_pRight);?? ????return?depthLeft?>?depthRight???(depthLeft?+?1)?:?(depthRight?+?1);??? }??
3. 前序遍歷,中序遍歷,后序遍歷
前序遍歷遞歸解法:
(1)如果二叉樹(shù)為空,空操作
(2)如果二叉樹(shù)不為空,訪問(wèn)根節(jié)點(diǎn),前序遍歷左子樹(shù),前序遍歷右子樹(shù)
參考代碼如下:
[cpp]?view plaincopy
void?PreOrderTraverse(BinaryTreeNode?*?pRoot)?? {?? ????if(pRoot?==?NULL)?? ????????return;?? ????Visit(pRoot);??? ????PreOrderTraverse(pRoot->m_pLeft);??? ????PreOrderTraverse(pRoot->m_pRight);??? }??
中序遍歷遞歸解法
(1)如果二叉樹(shù)為空,空操作。
(2)如果二叉樹(shù)不為空,中序遍歷左子樹(shù),訪問(wèn)根節(jié)點(diǎn),中序遍歷右子樹(shù)
參考代碼如下:
[cpp]?view plaincopy
void?InOrderTraverse(BinaryTreeNode?*?pRoot)?? {?? ????if(pRoot?==?NULL)?? ????????return;?? ????InOrderTraverse(pRoot->m_pLeft);??? ????Visit(pRoot);??? ????InOrderTraverse(pRoot->m_pRight);??? }??
后序遍歷遞歸解法
(1)如果二叉樹(shù)為空,空操作
(2)如果二叉樹(shù)不為空,后序遍歷左子樹(shù),后序遍歷右子樹(shù),訪問(wèn)根節(jié)點(diǎn)
參考代碼如下:
[cpp]?view plaincopy
void?PostOrderTraverse(BinaryTreeNode?*?pRoot)?? {?? ????if(pRoot?==?NULL)?? ????????return;?? ????PostOrderTraverse(pRoot->m_pLeft);??? ????PostOrderTraverse(pRoot->m_pRight);??? ????Visit(pRoot);??? }??
4.分層遍歷二叉樹(shù)(按層次從上往下,從左往右)
相當(dāng)于廣度優(yōu)先搜索,使用隊(duì)列實(shí)現(xiàn)。隊(duì)列初始化,將根節(jié)點(diǎn)壓入隊(duì)列。當(dāng)隊(duì)列不為空,進(jìn)行如下操作:彈出一個(gè)節(jié)點(diǎn),訪問(wèn),若左子節(jié)點(diǎn)或右子節(jié)點(diǎn)不為空,將其壓入隊(duì)列。
[cpp]?view plaincopy
void?LevelTraverse(BinaryTreeNode?*?pRoot)?? {?? ????if(pRoot?==?NULL)?? ????????return;?? ????queue<BinaryTreeNode?*>?q;?? ????q.push(pRoot);//添加元素到隊(duì)列尾部 ? ????while(!q.empty())?? ????{?? ????????BinaryTreeNode?*?pNode?=?q.front();//指向隊(duì)列的首部 ? ????????q.pop();//刪除首部元素(即指針) ? ????????Visit(pNode);??? ????????if(pNode->m_pLeft?!=?NULL)?? ????????????q.push(pNode->m_pLeft);//添加元素到隊(duì)列尾部?? ????????if(pNode->m_pRight?!=?NULL)?? ????????????q.push(pNode->m_pRight);//添加元素到隊(duì)列尾部?? ????}?? ????return;?? }??
5. 將二叉查找樹(shù)變?yōu)橛行虻碾p向鏈表
要求不能創(chuàng)建新節(jié)點(diǎn),只調(diào)整指針。
遞歸解法:
(1)如果二叉樹(shù)查找樹(shù)為空,不需要轉(zhuǎn)換,對(duì)應(yīng)雙向鏈表的第一個(gè)節(jié)點(diǎn)是NULL,最后一個(gè)節(jié)點(diǎn)是NULL
(2)如果二叉查找樹(shù)不為空:
如果左子樹(shù)為空,對(duì)應(yīng)雙向有序鏈表的第一個(gè)節(jié)點(diǎn)是根節(jié)點(diǎn),左邊不需要其他操作;
如果左子樹(shù)不為空,轉(zhuǎn)換左子樹(shù),二叉查找樹(shù)對(duì)應(yīng)雙向有序鏈表的第一個(gè)節(jié)點(diǎn)就是左子樹(shù)轉(zhuǎn)換后雙向有序鏈表的第一個(gè)節(jié)點(diǎn),同時(shí)將根節(jié)點(diǎn)和左子樹(shù)轉(zhuǎn)換后的雙向有序鏈表的最后一個(gè)節(jié)點(diǎn)連接;
如果右子樹(shù)為空,對(duì)應(yīng)雙向有序鏈表的最后一個(gè)節(jié)點(diǎn)是根節(jié)點(diǎn),右邊不需要其他操作;
如果右子樹(shù)不為空,對(duì)應(yīng)雙向有序鏈表的最后一個(gè)節(jié)點(diǎn)就是右子樹(shù)轉(zhuǎn)換后雙向有序鏈表的最后一個(gè)節(jié)點(diǎn),同時(shí)將根節(jié)點(diǎn)和右子樹(shù)轉(zhuǎn)換后的雙向有序鏈表的第一個(gè)節(jié)點(diǎn)連接。
參考代碼如下:
[cpp]?view plaincopy
? ? ? ? ? ?? void?Convert(BinaryTreeNode?*?pRoot,??? ?????????????BinaryTreeNode?*?&?pFirstNode,?BinaryTreeNode?*?&?pLastNode)?? {?? ????BinaryTreeNode?*pFirstLeft,?*pLastLeft,?*?pFirstRight,?*pLastRight;?? ????if(pRoot?==?NULL)??? ????{?? ????????pFirstNode?=?NULL;?? ????????pLastNode?=?NULL;?? ????????return;?? ????}?? ?? ????if(pRoot->m_pLeft?==?NULL)?? ????{?? ?????????? ????????pFirstNode?=?pRoot;?? ????}?? ????else?? ????{?? ????????Convert(pRoot->m_pLeft,?pFirstLeft,?pLastLeft);?? ?????????? ????????pFirstNode?=?pFirstLeft;?? ?????????? ????????pRoot->m_pLeft?=?pLastLeft;?? ????????pLastLeft->m_pRight?=?pRoot;?? ????}?? ?? ????if(pRoot->m_pRight?==?NULL)?? ????{?? ?????????? ????????pLastNode?=?pRoot;?? ????}?? ????else?? ????{?? ????????Convert(pRoot->m_pRight,?pFirstRight,?pLastRight);?? ?????????? ????????pLastNode?=?pLastRight;?? ?????????? ????????pRoot->m_pRight?=?pFirstRight;?? ????????pFirstRight->m_pLeft?=?pRoot;?? ????}?? ?? ????return;?? }??
6. 求二叉樹(shù)第K層的節(jié)點(diǎn)個(gè)數(shù)
遞歸解法:
(1)如果二叉樹(shù)為空或者k<1返回0
(2)如果二叉樹(shù)不為空并且k==1,返回1
(3)如果二叉樹(shù)不為空且k>1,返回左子樹(shù)中k-1層的節(jié)點(diǎn)個(gè)數(shù)與右子樹(shù)k-1層節(jié)點(diǎn)個(gè)數(shù)之和
參考代碼如下:
[cpp]?view plaincopy
int?GetNodeNumKthLevel(BinaryTreeNode?*?pRoot,?int?k)?? {?? ????if(pRoot?==?NULL?||?k?<?1)?? ????????return?0;?? ????if(k?==?1)?? ????????return?1;?? ????int?numLeft?=?GetNodeNumKthLevel(pRoot->m_pLeft,?k-1);??? ????int?numRight?=?GetNodeNumKthLevel(pRoot->m_pRight,?k-1);??? ????return?(numLeft?+?numRight);?? }??
7. 求二叉樹(shù)中葉子節(jié)點(diǎn)的個(gè)數(shù)
完全二叉樹(shù)有2*n-1 個(gè)節(jié)點(diǎn),則它的葉子節(jié)點(diǎn)數(shù)為?
完全二叉樹(shù)的節(jié)點(diǎn)數(shù)是奇數(shù),說(shuō)明此完全二叉樹(shù)也是滿二叉樹(shù),也就是說(shuō)每個(gè)內(nèi)部節(jié)點(diǎn)正好都有2個(gè)葉結(jié)點(diǎn).
設(shè)內(nèi)部節(jié)點(diǎn)數(shù)為a,葉節(jié)點(diǎn)數(shù)為b,結(jié)點(diǎn)總數(shù)為m,明顯有a+b=m (1)
非空滿二叉樹(shù)中所有節(jié)點(diǎn)的出度正好等于入度,每個(gè)內(nèi)部節(jié)點(diǎn)出度為2,葉節(jié)點(diǎn)出度為0,所有節(jié)點(diǎn)的出度和為2a;根節(jié)點(diǎn)入度為0,其他節(jié)點(diǎn)的入度為1,所有節(jié)點(diǎn)的入度和為a+b-1;因此有2a=a+b-1 (2)
由(1),(2)得 b=(m+1)/2,a=(m-1)/2,b=a+1
也就是說(shuō),非空滿二叉樹(shù)的葉節(jié)點(diǎn)數(shù)正好比內(nèi)部節(jié)點(diǎn)數(shù)多1
此完全二叉樹(shù)的結(jié)點(diǎn)總數(shù)為2n-1,因此其葉結(jié)點(diǎn)數(shù)為n.
遞歸解法:
(1)如果二叉樹(shù)為空,返回0
(2)如果二叉樹(shù)不為空且左右子樹(shù)為空,返回1
(3)如果二叉樹(shù)不為空,且左右子樹(shù)不同時(shí)為空,返回左子樹(shù)中葉子節(jié)點(diǎn)個(gè)數(shù)加上右子樹(shù)中葉子節(jié)點(diǎn)個(gè)數(shù)
參考代碼如下:
[cpp]?view plaincopy
int?GetLeafNodeNum(BinaryTreeNode?*?pRoot)?? {?? ????if(pRoot?==?NULL)?? ????????return?0;?? ????if(pRoot->m_pLeft?==?NULL?&&?pRoot->m_pRight?==?NULL)?? ????????return?1;?? ????int?numLeft?=?GetLeafNodeNum(pRoot->m_pLeft);??? ????int?numRight?=?GetLeafNodeNum(pRoot->m_pRight);??? ????return?(numLeft?+?numRight);?? } ?
8. 判斷兩棵二叉樹(shù)是否結(jié)構(gòu)相同
不考慮數(shù)據(jù)內(nèi)容。結(jié)構(gòu)相同意味著對(duì)應(yīng)的左子樹(shù)和對(duì)應(yīng)的右子樹(shù)都結(jié)構(gòu)相同。
遞歸解法:
(1)如果兩棵二叉樹(shù)都為空,返回真
(2)如果兩棵二叉樹(shù)一棵為空,另一棵不為空,返回假
(3)如果兩棵二叉樹(shù)都不為空,如果對(duì)應(yīng)的左子樹(shù)和右子樹(shù)都同構(gòu)返回真,其他返回假
參考代碼如下:
[cpp]?view plaincopy
bool?StructureCmp(BinaryTreeNode?*?pRoot1,?BinaryTreeNode?*?pRoot2)?? {?? ????if(pRoot1?==?NULL?&&?pRoot2?==?NULL)??? ????????return?true;?? ????else?if(pRoot1?==?NULL?||?pRoot2?==?NULL)??? ????????return?false;?? ????bool?resultLeft?=?StructureCmp(pRoot1->m_pLeft,?pRoot2->m_pLeft);??? ????bool?resultRight?=?StructureCmp(pRoot1->m_pRight,?pRoot2->m_pRight);??? ????return?(resultLeft?&&?resultRight);?? }???
9. 判斷二叉樹(shù)是不是平衡二叉樹(shù)
遞歸解法:
(1)如果二叉樹(shù)為空,返回真
(2)如果二叉樹(shù)不為空,如果左子樹(shù)和右子樹(shù)都是AVL樹(shù)并且左子樹(shù)和右子樹(shù)高度相差不大于1,返回真,其他返回假
參考代碼:
[cpp]?view plaincopy
bool?IsAVL(BinaryTreeNode?*?pRoot,?int?&?height)?? {?? ????if(pRoot?==?NULL)??? ????{?? ????????height?=?0;?? ????????return?true;?? ????}?? ????int?heightLeft;?? ????bool?resultLeft?=?IsAVL(pRoot->m_pLeft,?heightLeft);?? ????int?heightRight;?? ????bool?resultRight?=?IsAVL(pRoot->m_pRight,?heightRight);?? ????if(resultLeft?&&?resultRight?&&?abs(heightLeft?-?heightRight)?<=?1)??? ????{?? ????????height?=?max(heightLeft,?heightRight)?+?1;?? ????????return?true;?? ????}?? ????else?? ????{?? ????????height?=?max(heightLeft,?heightRight)?+?1;?? ????????return?false;?? ????}?? }??
10. 求二叉樹(shù)的鏡像
遞歸解法:
(1)如果二叉樹(shù)為空,返回空
(2)如果二叉樹(shù)不為空,求左子樹(shù)和右子樹(shù)的鏡像,然后交換左子樹(shù)和右子樹(shù)
參考代碼如下:
[cpp]?view plaincopy
BinaryTreeNode?*?Mirror(BinaryTreeNode?*?pRoot)?? {?? ????if(pRoot?==?NULL)??? ????????return?NULL;?? ????BinaryTreeNode?*?pLeft?=?Mirror(pRoot->m_pLeft);??? ????BinaryTreeNode?*?pRight?=?Mirror(pRoot->m_pRight);??? ?????????? ????pRoot->m_pLeft?=?pRight;?? ????pRoot->m_pRight?=?pLeft;?? ????return?pRoot;?? }??
11. 求二叉樹(shù)中兩個(gè)節(jié)點(diǎn)的最低公共祖先節(jié)點(diǎn)
遞歸解法:
(1)如果兩個(gè)節(jié)點(diǎn)分別在根節(jié)點(diǎn)的左子樹(shù)和右子樹(shù),則返回根節(jié)點(diǎn)
(2)如果兩個(gè)節(jié)點(diǎn)都在左子樹(shù),則遞歸處理左子樹(shù);如果兩個(gè)節(jié)點(diǎn)都在右子樹(shù),則遞歸處理右子樹(shù)
參考代碼如下:
[cpp]?view plaincopy
bool?FindNode(BinaryTreeNode?*?pRoot,?BinaryTreeNode?*?pNode)?? {?? ????if(pRoot?==?NULL?||?pNode?==?NULL)?? ????????return?false;?? ?? ????if(pRoot?==?pNode)?? ????????return?true;?? ?? ????bool?found?=?FindNode(pRoot->m_pLeft,?pNode);?? ????if(!found)?? ????????found?=?FindNode(pRoot->m_pRight,?pNode);?? ?? ????return?found;?? }?? ?? BinaryTreeNode?*?GetLastCommonParent(BinaryTreeNode?*?pRoot,??? ?????????????????????????????????????BinaryTreeNode?*?pNode1,??? ?????????????????????????????????????BinaryTreeNode?*?pNode2)?? {?? ????if(FindNode(pRoot->m_pLeft,?pNode1))?? ????{?? ????????if(FindNode(pRoot->m_pRight,?pNode2))?? ????????????return?pRoot;?? ????????else?? ????????????return?GetLastCommonParent(pRoot->m_pLeft,?pNode1,?pNode2);?? ????}?? ????else?? ????{?? ????????if(FindNode(pRoot->m_pLeft,?pNode2))?? ????????????return?pRoot;?? ????????else?? ????????????return?GetLastCommonParent(pRoot->m_pRight,?pNode1,?pNode2);?? ????}?? }??
遞歸解法效率很低,有很多重復(fù)的遍歷,下面看一下非遞歸解法。
非遞歸解法:
先求從根節(jié)點(diǎn)到兩個(gè)節(jié)點(diǎn)的路徑,然后再比較對(duì)應(yīng)路徑的節(jié)點(diǎn)就行,最后一個(gè)相同的節(jié)點(diǎn)也就是他們?cè)诙鏄?shù)中的最低公共祖先節(jié)點(diǎn)
參考代碼如下:
[cpp]?view plaincopy
bool?GetNodePath(BinaryTreeNode?*?pRoot,?BinaryTreeNode?*?pNode,??? ?????????????????list<BinaryTreeNode?*>?&?path)?? {?? ????if(pRoot?==?pNode)?? ????{????? ????????path.push_back(pRoot);?? ????????return?true;?? ????}?? ????if(pRoot?==?NULL)?? ????????return?false;?? ????path.push_back(pRoot);?? ????bool?found?=?false;?? ????found?=?GetNodePath(pRoot->m_pLeft,?pNode,?path);?? ????if(!found)?? ????????found?=?GetNodePath(pRoot->m_pRight,?pNode,?path);?? ????if(!found)?? ????????path.pop_back();?? ????return?found;?? }?? BinaryTreeNode?*?GetLastCommonParent(BinaryTreeNode?*?pRoot,?BinaryTreeNode?*?pNode1,?BinaryTreeNode?*?pNode2)?? {?? ????if(pRoot?==?NULL?||?pNode1?==?NULL?||?pNode2?==?NULL)?? ????????return?NULL;?? ????list<BinaryTreeNode*>?path1;?? ????bool?bResult1?=?GetNodePath(pRoot,?pNode1,?path1);?? ????list<BinaryTreeNode*>?path2;?? ????bool?bResult2?=?GetNodePath(pRoot,?pNode2,?path2);?? ????if(!bResult1?||?!bResult2)??? ????????return?NULL;?? ????BinaryTreeNode?*?pLast?=?NULL;?? ????list<BinaryTreeNode*>::const_iterator?iter1?=?path1.begin();?? ????list<BinaryTreeNode*>::const_iterator?iter2?=?path2.begin();?? ????while(iter1?!=?path1.end()?&&?iter2?!=?path2.end())?? ????{?? ????????if(*iter1?==?*iter2)?? ????????????pLast?=?*iter1;?? ????????else?? ????????????break;?? ????????iter1++;?? ????????iter2++;?? ????}?? ????return?pLast;?? }??
在上述算法的基礎(chǔ)上稍加變化即可求二叉樹(shù)中任意兩個(gè)節(jié)點(diǎn)的距離了。
12. 求二叉樹(shù)中節(jié)點(diǎn)的最大距離
即二叉樹(shù)中相距最遠(yuǎn)的兩個(gè)節(jié)點(diǎn)之間的距離。
遞歸解法:
(1)如果二叉樹(shù)為空,返回0,同時(shí)記錄左子樹(shù)和右子樹(shù)的深度,都為0
(2)如果二叉樹(shù)不為空,最大距離要么是左子樹(shù)中的最大距離,要么是右子樹(shù)中的最大距離,要么是左子樹(shù)節(jié)點(diǎn)中到根節(jié)點(diǎn)的最大距離+右子樹(shù)節(jié)點(diǎn)中到根節(jié)點(diǎn)的最大距離,同時(shí)記錄左子樹(shù)和右子樹(shù)節(jié)點(diǎn)中到根節(jié)點(diǎn)的最大距離。
參考代碼如下:
[cpp]?view plaincopy
int?GetMaxDistance(BinaryTreeNode?*?pRoot,?int?&?maxLeft,?int?&?maxRight)?? {?? ?????? ?????? ????if(pRoot?==?NULL)?? ????{?? ????????maxLeft?=?0;?? ????????maxRight?=?0;?? ????????return?0;?? ????}?? ????int?maxLL,?maxLR,?maxRL,?maxRR;?? ????int?maxDistLeft,?maxDistRight;?? ????if(pRoot->m_pLeft?!=?NULL)?? ????{?? ????????maxDistLeft?=?GetMaxDistance(pRoot->m_pLeft,?maxLL,?maxLR);?? ????????maxLeft?=?max(maxLL,?maxLR)?+?1;?? ????}?? ????else?? ????{?? ????????maxDistLeft?=?0;?? ????????maxLeft?=?0;?? ????}?? ????if(pRoot->m_pRight?!=?NULL)?? ????{?? ????????maxDistRight?=?GetMaxDistance(pRoot->m_pRight,?maxRL,?maxRR);?? ????????maxRight?=?max(maxRL,?maxRR)?+?1;?? ????}?? ????else?? ????{?? ????????maxDistRight?=?0;?? ????????maxRight?=?0;?? ????}?? ????return?max(max(maxDistLeft,?maxDistRight),?maxLeft+maxRight);?? }??
13. 由前序遍歷序列和中序遍歷序列重建二叉樹(shù)
二叉樹(shù)前序遍歷序列中,第一個(gè)元素總是樹(shù)的根節(jié)點(diǎn)的值。中序遍歷序列中,左子樹(shù)的節(jié)點(diǎn)的值位于根節(jié)點(diǎn)的值的左邊,右子樹(shù)的節(jié)點(diǎn)的值位
于根節(jié)點(diǎn)的值的右邊。
遞歸解法:
(1)如果前序遍歷為空或中序遍歷為空或節(jié)點(diǎn)個(gè)數(shù)小于等于0,返回NULL。
(2)創(chuàng)建根節(jié)點(diǎn)。
前序遍歷的第一個(gè)數(shù)據(jù)就是根節(jié)點(diǎn)的數(shù)據(jù),在中序遍歷中找到根節(jié)點(diǎn)的位置,可分別得知左子樹(shù)和右子樹(shù)的前序和中序遍
歷序列,重建左右子樹(shù)。
題目描述: 輸入某二叉樹(shù)的前序遍歷和中序遍歷的結(jié)果,請(qǐng)重建出該二叉樹(shù)。假設(shè)輸入的前序遍歷和中序遍歷的結(jié)果中都不含重復(fù)的數(shù)字。例如輸入前序遍歷序列{1,2,4,7,3,5,6,8}和中序遍歷序列{4,7,2,1,5,3,8,6},則重建二叉樹(shù)并輸出它的后序遍歷序列。
輸入: 輸入可能包含多個(gè)測(cè)試樣例,對(duì)于每個(gè)測(cè)試案例,
輸入的第一行為一個(gè)整數(shù)n(1<=n<=1000):代表二叉樹(shù)的節(jié)點(diǎn)個(gè)數(shù)。
輸入的第二行包括n個(gè)整數(shù)(其中每個(gè)元素a的范圍為(1<=a<=1000)):代表二叉樹(shù)的前序遍歷序列。
輸入的第三行包括n個(gè)整數(shù)(其中每個(gè)元素a的范圍為(1<=a<=1000)):代表二叉樹(shù)的中序遍歷序列。
輸出: 對(duì)應(yīng)每個(gè)測(cè)試案例,輸出一行:
如果題目中所給的前序和中序遍歷序列能構(gòu)成一棵二叉樹(shù),則輸出n個(gè)整數(shù),代表二叉樹(shù)的后序遍歷序列,每個(gè)元素后面都有空格。
如果題目中所給的前序和中序遍歷序列不能構(gòu)成一棵二叉樹(shù),則輸出”No”。
樣例輸入: 81 2 4 7 3 5 6 84 7 2 1 5 3 8 681 2 4 7 3 5 6 84 1 2 7 5 3 8 6 樣例輸出: 7 4 2 5 8 6 3 1 No
? ? 采用遞歸的方式重構(gòu)二叉樹(shù),關(guān)鍵是要考慮到一些特殊情況,比如:只有根節(jié)點(diǎn)的二叉樹(shù)、只有左子樹(shù)或只有右子樹(shù)的二叉樹(shù)以及二叉樹(shù)根節(jié)點(diǎn)為NULL、前序中序序列不匹配導(dǎo)致不能重構(gòu)二叉樹(shù)等。
? ? AC代碼如下(一直在如何實(shí)現(xiàn)判斷能否重構(gòu)二叉樹(shù)的地方徘徊,在九度論壇里大致看了下,借鑒了下各位前輩的思路:定義一個(gè)全局bool變量,用來(lái)跟蹤判斷能夠重構(gòu)):
[cpp]?view plaincopy
#include<stdio.h>?? #include<stdlib.h>?? ?? typedef?int?ElemType;?? typedef?struct?BTNode??? {?? ????ElemType?data;?? ????struct?BTNode?*left;?? ????struct?BTNode?*right;?? }BTNode,*BTree;?? ?? bool?CanReBuild;?????? ?? ? ? ?? void?RebuildBinaryTree(BTree?*ppTree,int?*pre,int?*inv,int?len)?? {?? ????if(p
總結(jié)
以上是生活随笔為你收集整理的一文搞定面试中的二叉树问题的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。