二叉树集锦

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. }  

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