摘要】計(jì)算機(jī)科學(xué)中,二叉樹(shù)是每個(gè)節(jié)點(diǎn)最多有兩個(gè)子樹(shù)的樹(shù)結(jié)構(gòu)。通常子樹(shù)被稱(chēng)作“左子樹(shù)”(left subtree)和“右子樹(shù)”(right subtree)。二叉樹(shù)常被用于實(shí)現(xiàn)二叉查找樹(shù)和二叉堆。二叉樹(shù)是遞歸定義的,因此,與二叉樹(shù)有關(guān)的題目基本都可以用遞歸思想解決,當(dāng)然有些題目非遞歸解法也應(yīng)該掌握,如非遞歸遍歷節(jié)點(diǎn)等等。本文努力對(duì)二叉樹(shù)相關(guān)題目做一個(gè)較全的整理總結(jié),希望對(duì)找工作的同學(xué)有所幫助。
本文內(nèi)容如下所示 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ù)
二叉樹(shù)節(jié)點(diǎn)定義
struct BinaryTreeNode
{
int m_nValue;BinaryTreeNode* m_pLeft;BinaryTreeNode* m_pRight;
};
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 參考代碼如下:
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 參考代碼如下:
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ù) 參考代碼如下:
void PreOrderTraverse(BinaryTreeNode
* pRoot)
{
if (pRoot
== NULL )
return ;printf(
"%d\n" ,pRoot
-> data ); PreOrderTraverse(pRoot
-> m_pLeft); PreOrderTraverse(pRoot
-> m_pRight);
}
中序遍歷遞歸解法 (1)如果二叉樹(shù)為空,空操作。 (2)如果二叉樹(shù)不為空,先遍歷左子樹(shù),然后訪問(wèn)根節(jié)點(diǎn),再遍歷右子樹(shù) 參考代碼如下:
void InOrderTraverse(BinaryTreeNode
* pRoot)
{
if (pRoot
== NULL )
return ;InOrderTraverse(pRoot
-> m_pLeft); printf(
"%d\n" ,pRoot
-> data ); InOrderTraverse(pRoot
-> m_pRight);
}
后序遍歷遞歸解法 (1)如果二叉樹(shù)為空,空操作。 (2)如果二叉樹(shù)不為空,先遍歷左子樹(shù),然后遍歷右子樹(shù),訪問(wèn)根節(jié)點(diǎn) 參考代碼如下:
void InOrderTraverse(BinaryTreeNode
* pRoot)
{
if (pRoot
== NULL )
return ;InOrderTraverse(pRoot
-> m_pLeft); InOrderTraverse(pRoot
-> m_pRight); printf(
"%d\n" ,pRoot
-> data );
}
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ì)列。
void LevelTraverse(BinaryTreeNode * pRoot)
{
if (pRoot == NULL)
return ;
queue <BinaryTreeNode *> q;q.push(pRoot);
while (!q.empty()){BinaryTreeNode * pNode = q.front();q.pop();Visit(pNode);
if (pNode->m_pLeft != NULL)q.push(pNode->m_pLeft);
if (pNode->m_pRight != NULL)q.push(pNode->m_pRight);}
return ;
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
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)連 接。 參考代碼如下:
/
***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***
參數(shù):
pRoot: 二叉查找樹(shù)根節(jié)點(diǎn)指針
pFirstNode: 轉(zhuǎn)換后雙向有序鏈表的第一個(gè)節(jié)點(diǎn)指針
pLastNode: 轉(zhuǎn)換后雙向有序鏈表的最后一個(gè)節(jié)點(diǎn)指針
***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** *** /
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)
{
// 如果左子樹(shù)為空,對(duì)應(yīng)雙向有序鏈表的第一個(gè)節(jié)點(diǎn)是根節(jié)點(diǎn)
pFirstNode = pRoot;
}
else
{
Convert(pRoot->m_pLeft, pFirstLeft, pLastLeft);
// 二叉查找樹(shù)對(duì)應(yīng)雙向有序鏈表的第一個(gè)節(jié)點(diǎn)就是左子樹(shù)轉(zhuǎn)換后雙向有序鏈表的第一個(gè)節(jié)點(diǎn)
pFirstNode = pFirstLeft;
// 將根節(jié)點(diǎn)和左子樹(shù)轉(zhuǎn)換后的雙向有序鏈表的最后一個(gè)節(jié)點(diǎn)連接
pRoot->m_pLeft = pLastLeft;
pLastLeft->m_pRight = pRoot;
} if(pRoot->m_pRight == NULL)
{
// 對(duì)應(yīng)雙向有序鏈表的最后一個(gè)節(jié)點(diǎn)是根節(jié)點(diǎn)
pLastNode = pRoot;
}
else
{
Convert(pRoot->m_pRight, pFirstRight, pLastRight);
// 對(duì)應(yīng)雙向有序鏈表的最后一個(gè)節(jié)點(diǎn)就是右子樹(shù)轉(zhuǎn)換后雙向有序鏈表的最后一個(gè)節(jié)點(diǎn)
pLastNode = pLastRight;
// 將根節(jié)點(diǎn)和右子樹(shù)轉(zhuǎn)換后的雙向有序鏈表的第一個(gè)節(jié)點(diǎn)連接
pRoot->m_pRight = pFirstRight;
pFirstRight->m_pLeft = pRoot;
} return;
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
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ù)之和 參考代碼如下:
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ù)
遞歸解法: (1)如果二叉樹(shù)為空,返回0 (2)如果二叉樹(shù)不為空且左右子樹(shù)為空,返回1 (3)如果二叉樹(shù)不為空,且左右子樹(shù)不同時(shí)為空,返回左子樹(shù)中葉子節(jié)點(diǎn)個(gè)數(shù)加上右子樹(shù)中葉子節(jié)點(diǎn)個(gè)數(shù) 參考代碼如下:
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)返回真,其他返回假 參考代碼如下:
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,返回真,其他返回假 參考代碼:
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 ;}
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
10、求二叉樹(shù)的鏡像
遞歸解法: (1)如果二叉樹(shù)為空,返回空 (2)如果二叉樹(shù)不為空,求左子樹(shù)和右子樹(shù)的鏡像,然后交換左子樹(shù)和右子樹(shù) 參考代碼如下:
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ù) 參考代碼如下:
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);}
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
分析: 遞歸解法效率很低,有很多重復(fù)的遍歷,下面看一下非遞歸解法。 非遞歸解法: 先求從根節(jié)點(diǎn)到兩個(gè)節(jié)點(diǎn)的路徑,然后再比較對(duì)應(yīng)路徑的節(jié)點(diǎn)就行,最后一個(gè)相同的節(jié)點(diǎn)也就是他們?cè)诙鏄?shù)中的最低公共祖先節(jié)點(diǎn) 參考代碼如下:
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;
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
在上述算法的基礎(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)的最大距離。 參考代碼如下:
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);
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
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ù)。
BinaryTreeNode * RebuildBinaryTree(
int * pPreOrder,
int * pInOrder,
int nodeNum)
{
if (pPreOrder ==
NULL || pInOrder ==
NULL || nodeNum <=
0 )
return NULL ;BinaryTreeNode * pRoot = new BinaryTreeNode;pRoot->m_nValue = pPreOrder[
0 ];pRoot->m_pLeft =
NULL ;pRoot->m_pRight =
NULL ;
int rootPositionInOrder = -
1 ;
for (
int i =
0 ; i < nodeNum; i++)
if (pInOrder[i] == pRoot->m_nValue){rootPositionInOrder = i;
break ;}
if (rootPositionInOrder == -
1 ){throw std::exception(
"Invalid input." );}
int nodeNumLeft = rootPositionInOrder;
int * pPreOrderLeft = pPreOrder +
1 ;
int * pInOrderLeft = pInOrder;pRoot->m_pLeft = RebuildBinaryTree(pPreOrderLeft, pInOrderLeft, nodeNumLeft);
int nodeNumRight = nodeNum - nodeNumLeft -
1 ;
int * pPreOrderRight = pPreOrder +
1 + nodeNumLeft;
int * pInOrderRight = pInOrder + nodeNumLeft +
1 ;pRoot->m_pRight = RebuildBinaryTree(pPreOrderRight, pInOrderRight, nodeNumRight);
return pRoot;
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
同樣,有中序遍歷序列和后序遍歷序列,類(lèi)似的方法可重建二叉樹(shù),但前序遍歷序列和后序遍歷序列不同恢復(fù)一棵二叉樹(shù),證明略。
14、判斷二叉樹(shù)是不是完全二叉樹(shù)
若設(shè)二叉樹(shù)的深度為h,除第 h 層外,其它各層 (1~h-1) 的結(jié)點(diǎn)數(shù)都達(dá)到最大個(gè)數(shù),第 h 層所有的結(jié)點(diǎn)都連續(xù)集中在最左邊,這就是完全 二叉樹(shù)。 有如下算法,按層次(從上到下,從左到右)遍歷二叉樹(shù),當(dāng)遇到一個(gè)節(jié)點(diǎn)的左子樹(shù)為空時(shí),則該節(jié)點(diǎn)右子樹(shù)必須為空,且后面遍歷的節(jié)點(diǎn)左 右子樹(shù)都必須為空,否則不是完全二叉樹(shù)。
bool IsCompleteBinaryTree(BinaryTreeNode
* pRoot)
{
if (pRoot
== NULL )
return false ;
queue < BinaryTreeNode
*> q;q
. push(pRoot);bool mustHaveNoChild
= false ;bool result
= true ;
while (
! q
. empty()){BinaryTreeNode
* pNode
= q
. front();q
. pop();
if (mustHaveNoChild) {
if (pNode
-> m_pLeft
!= NULL || pNode
-> m_pRight
!= NULL ){result
= false ;break;}}
else {
if (pNode
-> m_pLeft
!= NULL && pNode
-> m_pRight
!= NULL ){q
. push(pNode
-> m_pLeft);q
. push(pNode
-> m_pRight);}
else if (pNode
-> m_pLeft
!= NULL && pNode
-> m_pRight
== NULL ){mustHaveNoChild
= true ;q
. push(pNode
-> m_pLeft);}
else if (pNode
-> m_pLeft
== NULL && pNode
-> m_pRight
!= NULL ){result
= false ;break;}
else {mustHaveNoChild
= true ;}}}
return result;
}
總結(jié)
以上是生活随笔 為你收集整理的数据结构-二叉树面试 常考 的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
如果覺(jué)得生活随笔 網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔 推薦給好友。