日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

数据结构-二叉树面试 常考

發(fā)布時(shí)間:2025/3/21 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 数据结构-二叉树面试 常考 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
摘要】計(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
  • 2
  • 3
  • 4
  • 5
  • 6

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; }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

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); }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

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); // 顯示結(jié)點(diǎn)數(shù)據(jù)PreOrderTraverse(pRoot->m_pLeft); // 前序遍歷左子樹(shù)PreOrderTraverse(pRoot->m_pRight); // 前序遍歷右子樹(shù) }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

中序遍歷遞歸解法
(1)如果二叉樹(shù)為空,空操作。
(2)如果二叉樹(shù)不為空,先遍歷左子樹(shù),然后訪問(wèn)根節(jié)點(diǎn),再遍歷右子樹(shù)
參考代碼如下:

void InOrderTraverse(BinaryTreeNode * pRoot) {if(pRoot == NULL)return;InOrderTraverse(pRoot->m_pLeft); // 中序遍歷左子樹(shù)printf("%d\n",pRoot->data); // 顯示結(jié)點(diǎn)數(shù)據(jù)InOrderTraverse(pRoot->m_pRight); // 中序遍歷右子樹(shù) }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

后序遍歷遞歸解法
(1)如果二叉樹(shù)為空,空操作。
(2)如果二叉樹(shù)不為空,先遍歷左子樹(shù),然后遍歷右子樹(shù),訪問(wèn)根節(jié)點(diǎn)
參考代碼如下:

void InOrderTraverse(BinaryTreeNode * pRoot) {if(pRoot == NULL)return;InOrderTraverse(pRoot->m_pLeft); // 后序遍歷左子樹(shù)InOrderTraverse(pRoot->m_pRight); // 后序遍歷右子樹(shù)printf("%d\n",pRoot->data); // 顯示結(jié)點(diǎn)數(shù)據(jù) }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

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); // 訪問(wèn)節(jié)點(diǎn)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); // 左子樹(shù)中k-1層的節(jié)點(diǎn)個(gè)數(shù)int numRight = GetNodeNumKthLevel(pRoot->m_pRight, k-1); // 右子樹(shù)中k-1層的節(jié)點(diǎn)個(gè)數(shù)return (numLeft + numRight); }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

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); // 左子樹(shù)中葉節(jié)點(diǎn)的個(gè)數(shù)int numRight = GetLeafNodeNum(pRoot->m_pRight); // 右子樹(shù)中葉節(jié)點(diǎn)的個(gè)數(shù)return (numLeft + numRight); }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

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) // 有一個(gè)為空,一個(gè)不為空,返回假return false;bool resultLeft = StructureCmp(pRoot1->m_pLeft, pRoot2->m_pLeft); // 比較對(duì)應(yīng)左子樹(shù) bool resultRight = StructureCmp(pRoot1->m_pRight, pRoot2->m_pRight); // 比較對(duì)應(yīng)右子樹(shù)return (resultLeft && resultRight); }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

9、 判斷二叉樹(shù)是不是平衡二叉樹(shù)

遞歸解法:
(1)如果二叉樹(shù)為空,返回真
(2)如果二叉樹(shù)不為空,如果左子樹(shù)和右子樹(shù)都是AVL樹(shù)并且左子樹(shù)和右子樹(shù)高度相差不大于1,返回真,其他返回假
參考代碼:

bool IsAVL(BinaryTreeNode * pRoot, int & height) {if(pRoot == NULL) // 空樹(shù),返回真{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) // 左子樹(shù)和右子樹(shù)都是AVL,并且高度相差不大于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) // 返回NULLreturn NULL;BinaryTreeNode * pLeft = Mirror(pRoot->m_pLeft); // 求左子樹(shù)鏡像BinaryTreeNode * pRight = Mirror(pRoot->m_pRight); // 求右子樹(shù)鏡像// 交換左子樹(shù)和右子樹(shù)pRoot->m_pLeft = pRight;pRoot->m_pRight = pLeft;return pRoot; }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

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;elsereturn GetLastCommonParent(pRoot->m_pLeft, pNode1, pNode2);}else{if(FindNode(pRoot->m_pLeft, pNode2))return pRoot;elsereturn 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;elsebreak;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) {// maxLeft, 左子樹(shù)中的節(jié)點(diǎn)距離根節(jié)點(diǎn)的最遠(yuǎn)距離// maxRight, 右子樹(shù)中的節(jié)點(diǎn)距離根節(jié)點(diǎn)的最遠(yuǎn)距離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;// 前序遍歷的第一個(gè)數(shù)據(jù)就是根節(jié)點(diǎn)數(shù)據(jù)pRoot->m_nValue = pPreOrder[0];pRoot->m_pLeft = NULL;pRoot->m_pRight = NULL;// 查找根節(jié)點(diǎn)在中序遍歷中的位置,中序遍歷中,根節(jié)點(diǎn)左邊為左子樹(shù),右邊為右子樹(shù)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.");}// 重建左子樹(shù)int nodeNumLeft = rootPositionInOrder;int * pPreOrderLeft = pPreOrder + 1;int * pInOrderLeft = pInOrder;pRoot->m_pLeft = RebuildBinaryTree(pPreOrderLeft, pInOrderLeft, nodeNumLeft);// 重建右子樹(shù)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) // 已經(jīng)出現(xiàn)了有空子樹(shù)的節(jié)點(diǎn)了,后面出現(xiàn)的必須為葉節(jié)點(diǎn)(左右子樹(shù)都為空){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ò),歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 女人高潮特级毛片 | 欧美日韩一区二区三区免费 | 特黄网站 | av中文在线| 91精品视频一区 | 男女在线视频 | 婷婷综合激情 | 人妻少妇偷人精品久久性色 | 欧洲亚洲视频 | 国产aⅴ一区二区三区 | 亚洲日本片 | 欧美日韩一二三四区 | 在线观看国产黄 | 黄色一级免费看 | 人妖粗暴刺激videos呻吟 | 亚州国产精品 | 中国极品少妇videossexhd 就要干就要操 | 国产香蕉视频在线观看 | 亚洲精品久久久中文字幕痴女 | 国产日韩欧美精品一区二区 | 久久视频网 | 女警白嫩翘臀呻吟迎合 | 91欧美日韩麻豆精品 | 亚洲精品小说 | 猛男被粗大男男1069 | 亚洲一区二区视频 | 婷婷成人综合 | www一级片 | 亚洲最大的成人网 | 日韩中文字幕国产 | 午夜高潮 | www.精品久久 | 日韩一级在线视频 | 免费萌白酱国产一区二区三区 | 欧美性大战久久久久久久 | 男男野外做爰全过程69 | 成人欧美精品一区二区 | 大胸美女啪啪 | 人妻换人妻a片爽麻豆 | 在线高清av | 神马午夜在线观看 | 91蜜桃传媒精品久久久一区二区 | 色www情 | 欧美一区二区激情 | 亚洲精品国产一区二 | 色屁屁一区二区三区 | 欧美日韩精品网站 | 美味的客房沙龙服务 | 蝌蚪自拍网站 | 91大神久久 | 性折磨bdsm欧美激情另类 | 91黑丝美女 | 精品福利一区二区三区 | 97超碰人人看 | 91天天色 | 欧美群妇大交群 | 日韩丰满少妇无码内射 | 日本在线第一页 | wwwxx国产 | 久久亚洲一区二区三区四区五区 | 黑人玩弄人妻一区二区绿帽子 | 谁有毛片网站 | 欧美中文字幕一区二区 | 少妇人妻偷人精品无码视频新浪 | 荫蒂被男人添免费视频 | 欧美一级爱爱视频 | 长篇高h乱肉辣文 | 日本在线不卡一区 | 色播在线观看 | 日韩免费看片 | 善良的女邻居在线观看 | 韩国成人免费视频 | 久久依人 | 国产孕妇孕交大片孕 | 黑人vs亚洲人在线播放 | 无遮挡国产 | 欧美黑人又粗又大又爽免费 | 九九久久免费视频 | 久久久久网 | 成人免费看片' | 亚洲自拍偷拍一区二区 | 亚洲色图综合在线 | 美女四肢被绑在床扒衣 | www免费黄色 | 日批黄色| 欧美一区二区三区免费观看 | 一级片观看| 日韩精品自拍 | 99精品视频在线免费观看 | 日本欧美一级片 | 天天干天天摸天天操 | 久久久久久久影院 | 黄色在线免费观看网站 | 日韩欧美黄 | 麻豆传媒在线播放 | 精品久久久久久久中文字幕 | 在线婷婷| 国产精品色片 | 欧美日本色 |