二叉樹集錦

1. 求二叉樹第K層的節點個數

遞歸解法:

(1)如果二叉樹爲空或者k<1返回0
(2)如果二叉樹不爲空並且k==1,返回1
(3)如果二叉樹不爲空且k>1,返回左子樹中k-1層的節點個數與右子樹k-1層節點個數之和
參考代碼如下:
  1. int GetNodeNumKthLevel(BinaryTreeNode * pRoot, int k)  
  2. {  
  3.     if(pRoot == NULL || k < 1)  
  4.         return 0;  
  5.     if(k == 1)  
  6.         return 1;  
  7.     int numLeft = GetNodeNumKthLevel(pRoot->m_pLeft, k-1); // 左子樹中k-1層的節點個數  
  8.     int numRight = GetNodeNumKthLevel(pRoot->m_pRight, k-1); // 右子樹中k-1層的節點個數  
  9.     return (numLeft + numRight);  
  10. }  

2. 判斷二叉樹是不是平衡二叉樹

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

  1. bool IsAVL(BinaryTreeNode * pRoot, int & height)  
  2. {  
  3.     if(pRoot == NULL) // 空樹,返回真  
  4.     {  
  5.         height = 0;  
  6.         return true;  
  7.     }  
  8.     int heightLeft;  
  9.     bool resultLeft = IsAVL(pRoot->m_pLeft, heightLeft);  
  10.     int heightRight;  
  11.     bool resultRight = IsAVL(pRoot->m_pRight, heightRight);  
  12.     if(resultLeft && resultRight && abs(heightLeft - heightRight) <= 1) // 左子樹和右子樹都是AVL,並且高度相差不大於1,返回真  
  13.     {  
  14.         height = max(heightLeft, heightRight) + 1;  
  15.         return true;  
  16.     }  
  17.     else  
  18.     {  
  19.         height = max(heightLeft, heightRight) + 1;  
  20.         return false;  
  21.     }  
  22. }  

3. 求二叉樹中節點的最大距離

即二叉樹中相距最遠的兩個節點之間的距離。
遞歸解法:
(1)如果二叉樹爲空,返回0,同時記錄左子樹和右子樹的深度,都爲0
(2)如果二叉樹不爲空,最大距離要麼是左子樹中的最大距離,要麼是右子樹中的最大距離,要麼是左子樹節點中到根節點的最大距離+右子樹節點中到根節點的最大距離,同時記錄左子樹和右子樹節點中到根節點的最大距離。

參考代碼如下:

  1. int GetMaxDistance(BinaryTreeNode * pRoot, int & maxLeft, int & maxRight)  
  2. {  
  3.     // maxLeft, 左子樹中的節點距離根節點的最遠距離  
  4.     // maxRight, 右子樹中的節點距離根節點的最遠距離  
  5.     if(pRoot == NULL)  
  6.     {  
  7.         maxLeft = 0;  
  8.         maxRight = 0;  
  9.         return 0;  
  10.     }  
  11.     int maxLL, maxLR, maxRL, maxRR;  
  12.     int maxDistLeft, maxDistRight;  
  13.     if(pRoot->m_pLeft != NULL)  
  14.     {  
  15.         maxDistLeft = GetMaxDistance(pRoot->m_pLeft, maxLL, maxLR);  
  16.         maxLeft = max(maxLL, maxLR) + 1;  
  17.     }  
  18.     else  
  19.     {  
  20.         maxDistLeft = 0;  
  21.         maxLeft = 0;  
  22.     }  
  23.     if(pRoot->m_pRight != NULL)  
  24.     {  
  25.         maxDistRight = GetMaxDistance(pRoot->m_pRight, maxRL, maxRR);  
  26.         maxRight = max(maxRL, maxRR) + 1;  
  27.     }  
  28.     else  
  29.     {  
  30.         maxDistRight = 0;  
  31.         maxRight = 0;  
  32.     }  
  33.     return max(max(maxDistLeft, maxDistRight), maxLeft+maxRight);  
  34. }  


4. 由前序遍歷序列和中序遍歷序列重建二叉樹

二叉樹前序遍歷序列中,第一個元素總是樹的根節點的值。中序遍歷序列中,左子樹的節點的值位於根節點的值的左邊,右子樹的節點的值位
於根節點的值的右邊。
遞歸解法:
(1)如果前序遍歷爲空或中序遍歷爲空或節點個數小於等於0,返回NULL。
(2)創建根節點。前序遍歷的第一個數據就是根節點的數據,在中序遍歷中找到根節點的位置,可分別得知左子樹和右子樹的前序和中序遍
歷序列,重建左右子樹。

  1. BinaryTreeNode * RebuildBinaryTree(int* pPreOrder, int* pInOrder, int nodeNum)  
  2. {  
  3.     if(pPreOrder == NULL || pInOrder == NULL || nodeNum <= 0)  
  4.         return NULL;  
  5.     BinaryTreeNode * pRoot = new BinaryTreeNode;  
  6.     // 前序遍歷的第一個數據就是根節點數據  
  7.     pRoot->m_nValue = pPreOrder[0];  
  8.     pRoot->m_pLeft = NULL;  
  9.     pRoot->m_pRight = NULL;  
  10.     // 查找根節點在中序遍歷中的位置,中序遍歷中,根節點左邊爲左子樹,右邊爲右子樹  
  11.     int rootPositionInOrder = -1;  
  12.     for(int i = 0; i < nodeNum; i++)  
  13.         if(pInOrder[i] == pRoot->m_nValue)  
  14.         {  
  15.             rootPositionInOrder = i;  
  16.             break;  
  17.         }  
  18.     if(rootPositionInOrder == -1)  
  19.     {  
  20.         throw std::exception("Invalid input.");  
  21.     }  
  22.     // 重建左子樹  
  23.     int nodeNumLeft = rootPositionInOrder;  
  24.     int * pPreOrderLeft = pPreOrder + 1;  
  25.     int * pInOrderLeft = pInOrder;  
  26.     pRoot->m_pLeft = RebuildBinaryTree(pPreOrderLeft, pInOrderLeft, nodeNumLeft);  
  27.     // 重建右子樹  
  28.     int nodeNumRight = nodeNum - nodeNumLeft - 1;  
  29.     int * pPreOrderRight = pPreOrder + 1 + nodeNumLeft;  
  30.     int * pInOrderRight = pInOrder + nodeNumLeft + 1;  
  31.     pRoot->m_pRight = RebuildBinaryTree(pPreOrderRight, pInOrderRight, nodeNumRight);  
  32.     return pRoot;  
  33. }  
同樣,有中序遍歷序列和後序遍歷序列,類似的方法可重建二叉樹,但前序遍歷序列和後序遍歷序列不同恢復一棵二叉樹,證明略。

5.判斷二叉樹是不是完全二叉樹

若設二叉樹的深度爲h,除第 h 層外,其它各層 (1~h-1) 的結點數都達到最大個數,第 h 層所有的結點都連續集中在最左邊,這就是完全
二叉樹。
有如下算法,按層次(從上到下,從左到右)遍歷二叉樹,當遇到一個節點的左子樹爲空時,則該節點右子樹必須爲空,且後面遍歷的節點左
右子樹都必須爲空,否則不是完全二叉樹。

  1. bool IsCompleteBinaryTree(BinaryTreeNode * pRoot)  
  2. {  
  3.     if(pRoot == NULL)  
  4.         return false;  
  5.     queue<BinaryTreeNode *> q;  
  6.     q.push(pRoot);  
  7.     bool mustHaveNoChild = false;  
  8.     bool result = true;  
  9.     while(!q.empty())  
  10.     {  
  11.         BinaryTreeNode * pNode = q.front();  
  12.         q.pop();  
  13.         if(mustHaveNoChild) // 已經出現了有空子樹的節點了,後面出現的必須爲葉節點(左右子樹都爲空)  
  14.         {  
  15.             if(pNode->m_pLeft != NULL || pNode->m_pRight != NULL)  
  16.             {  
  17.                 result = false;  
  18.                 break;  
  19.             }  
  20.         }  
  21.         else  
  22.         {  
  23.             if(pNode->m_pLeft != NULL && pNode->m_pRight != NULL)  
  24.             {  
  25.                 q.push(pNode->m_pLeft);  
  26.                 q.push(pNode->m_pRight);  
  27.             }  
  28.             else if(pNode->m_pLeft != NULL && pNode->m_pRight == NULL)  
  29.             {  
  30.                 mustHaveNoChild = true;  
  31.                 q.push(pNode->m_pLeft);  
  32.             }  
  33.             else if(pNode->m_pLeft == NULL && pNode->m_pRight != NULL)  
  34.             {  
  35.                 result = false;  
  36.                 break;  
  37.             }  
  38.             else  
  39.             {  
  40.                 mustHaveNoChild = true;  
  41.             }  
  42.         }  
  43.     }  
  44.     return result;  
  45. }  

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章