二叉树

二叉树节点定义如下:
struct BinaryTreeNode
{
    int Value;
    BinaryTreeNode*  Left;
    BinaryTreeNode*  Right;
};

相关链接:
轻松搞定面试中的链表题目

题目列表:

1. 求二叉树中的节点个数
2. 求二叉树的深度
3. 前序遍历,中序遍历,后序遍历
4.分层遍历二叉树(按层次从上往下,从左往右)
5. 将二叉查找树变为有序的双向链表
6. 求二叉树第K层的节点个数
7. 求二叉树中叶子节点的个数
8. 判断两棵二叉树是否结构相同
9. 判断二叉树是不是平衡二叉树
10. 求二叉树的镜像
11. 求二叉树中两个节点的最低/近公共祖先节点
12. 求二叉树中节点的最大距离
13. 由前序遍历序列和中序遍历序列重建二叉树
14.判断二叉树是不是完全二叉树

15、交换左右儿子

16、判断一个节点是否在一棵树中

 17、判断一棵树是不是二叉查找树(BST)

18、给出有序数组,求出高度最小的二叉查找树

19、由前序中序求出后序

详细解答

1. 求二叉树中的节点个数
递归解法:
(1)如果二叉树为空,节点个数为0
(2)如果二叉树不为空,二叉树节点个数 = 左子树节点个数 + 右子树节点个数 + 1
参考代码如下: 

  1. int GetNodeNum(BinaryTreeNode * Root)  
  2. {  
  3.     if(Root == NULL)    // 递归出口  
  4.         return 0;  
  5.     return GetNodeNum(Root->Left) + GetNodeNum(Root->Right) + 1;  
  6. }  

2. 求二叉树的深度
递归解法:
(1)如果二叉树为空,二叉树的深度为0
(2)如果二叉树不为空,二叉树的深度 = max(左子树深度, 右子树深度) + 1
参考代码如下:

  1. int GetDepth(BinaryTreeNode * Root)  
  2. {  
  3.     if(Root == NULL) // 递归出口  
  4.         return 0;  
  5.     int depthLeft = GetDepth(Root->Left);  
  6.     int depthRight = GetDepth(Root->Right);  
  7.     return depthLeft > depthRight ? (depthLeft + 1) : (depthRight + 1);   
  8. }  

3. 前序遍历,中序遍历,后序遍历
前序遍历递归解法:
(1)如果二叉树为空,空操作
(2)如果二叉树不为空,访问根节点,前序遍历左子树,前序遍历右子树
参考代码如下:

  1. void PreOrderTraverse(BinaryTreeNode * Root)  
  2. {  
  3.     if(Root == NULL)  
  4.         return;  
  5.     Visit(Root); // 访问根节点  
  6.     PreOrderTraverse(Root->Left); // 前序遍历左子树  
  7.     PreOrderTraverse(Root->Right); // 前序遍历右子树  
  8. }  

中序遍历递归解法
(1)如果二叉树为空,空操作。
(2)如果二叉树不为空,中序遍历左子树,访问根节点,中序遍历右子树
参考代码如下:

  1. void InOrderTraverse(BinaryTreeNode * Root)  
  2. {  
  3.     if(Root == NULL)  
  4.         return;  
  5.     InOrderTraverse(Root->Left);    // 中序遍历左子树  
  6.     Visit(Root);                    // 访问根节点  
  7.     InOrderTraverse(Root->Right); // 中序遍历右子树  
  8. }  

后序遍历递归解法
(1)如果二叉树为空,空操作
(2)如果二叉树不为空,后序遍历左子树,后序遍历右子树,访问根节点
参考代码如下:

  1. void PostOrderTraverse(BinaryTreeNode * Root)  
  2. {  
  3.     if(Root == NULL)  
  4.         return;  
  5.     PostOrderTraverse(Root->Left); // 后序遍历左子树  
  6.     PostOrderTraverse(Root->ight); // 后序遍历右子树  
  7.     Visit(Root);            // 访问根节点  
  8. }  

4.分层遍历二叉树(按层次从上往下,从左往右)

递归:

 

  1. int PrintNodeAtLevel(BiTree root, int level)   //遍历指定的某层
  2. {  
  3.     if(root==NULL || level < 0)  
  4.          return 0;  
  5.     else if(level == 0)  
  6.     {  
  7.         cout << root->data << endl;  
  8.         return 1;  
  9.     }  
  10.     else  
  11.         return PrintNodeAtLevel(root->left, level - 1) + PrintNodeAtLevel(root->right, level - 1);  
  12. }  

相当于广度优先搜索,使用队列实现。队列初始化,将根节点压入队列。当队列不为空,进行如下操作:弹出一个节点,访问,若左子节点或右子节点不为空,将其压入队列。

 
    1. void LevelOrder(BiTree root)
    2. {
    3.      InitQueue(Q);               //初始化队列
    4.     
    5.      BiTree p;
    6.      EnQueue(Q,root);            //将根节点入队
    7.      while(!IsEmpty(Q))          //队列不空循环
    8.      {
    9.          DeQueue(Q,p);          //访问p所指向节点
    10.          visit(p);
    11.         if(p->lchild != NULL)
    12.               EnQueue(Q,p->lchild);         //左子树不空则左子树入队
    13.         if(p->rchild != NULL)
    14.               EnQueue(Q,p->rchild);
    15.       }
    16. }
  1. //深度优先遍历:
    1. void DepthFirstTravel(Tree *root)  
    2. {  
    3.     stack<Tree *> s;  
    4.     s.push(root);  
    5.     while(!s.empty())  
    6.     {  
    7.         root = s.top();  
    8.         cout << root->data << " ";  
    9.         s.pop();  
    10.         if(root->rchild != NULL)  
    11.         {  
    12.             s.push(root->rchild);  
    13.         }  
    14.         if(root->lchild != NULL)  
    15.         {  
    16.             s.push(root->lchild);  
    17.         }  
    18.     }  
    19. }  

5. 将二叉查找树变为有序的双向链表

 

要求不能创建新节点,只调整指针。
递归解法:
(1)如果二叉树查找树为空,不需要转换,对应双向链表的第一个节点是NULL,最后一个节点是NULL
(2)如果二叉查找树不为空:

如果左子树为空,对应双向有序链表的第一个节点是根节点,左边不需要其他操作;
如果左子树不为空,转换左子树,二叉查找树对应双向有序链表的第一个节点就是左子树转换后双向有序链表的第一个节点,同时将根节点和左子树转换后的双向有序链 表的最后一个节点连接;
如果右子树为空,对应双向有序链表的最后一个节点是根节点,右边不需要其他操作;
如果右子树不为空,对应双向有序链表的最后一个节点就是右子树转换后双向有序链表的最后一个节点,同时将根节点和右子树转换后的双向有序链表的第一个节点连 接。

参考代码如下:

[cpp] view plain copy
 
 
 
  1. /****************************************************************************** 
  2. 参数: 
  3. pRoot: 二叉查找树根节点指针 
  4. pFirstNode: 转换后双向有序链表的第一个节点指针 
  5. pLastNode: 转换后双向有序链表的最后一个节点指针 
  6. ******************************************************************************/  
  7. void Convert(BinaryTreeNode * Root, BinaryTreeNode * & FirstNode, BinaryTreeNode * & LastNode)  
  8. {  
  9.     BinaryTreeNode *FirstLeft, *LastLeft, * FirstRight, *LastRight;  
  10.     if(Root == NULL)   
  11.     {  
  12.         FirstNode = NULL;  
  13.         LastNode = NULL;  
  14.         return;  
  15.     }  
  16.   
  17.     if(Root->Left == NULL)  
  18.     {   
  19.         FirstNode = Root;  // 如果左子树为空,对应双向有序链表的第一个节点是根节点  
  20.     }  
  21.     else  
  22.     {  
  23.         Convert(Root->Left, FirstLeft, LastLeft);  
  24.          // 二叉查找树对应双向有序链表的第一个节点就是左子树转换后双向有序链表的第一个节点  
  25.        FirstNode = FirstLeft;  
  26.                                   // 将根节点和左子树转换后的双向有序链表的最后一个节点连接  
  27.        Root->Left = LastLeft;  
  28.        LastLeft->Right = Root;  
  29.     }  
  30.   
  31.     if(Root->Right == NULL)  
  32.     {  
  33.          LastNode = Root;    // 对应双向有序链表的最后一个节点是根节点  
  34.     }  
  35.     else  
  36.     {  
  37.         Convert(Root->Right, FirstRight, LastRight);  
  38.         // 对应双向有序链表的最后一个节点就是右子树转换后双向有序链表的最后一个节点  
  39.         LastNode = LastRight;  
  40.                                      // 将根节点和右子树转换后的双向有序链表的第一个节点连接  
  41.         Root->Right = FirstRight;  
  42.         FirstRight->Left = Root;  
  43.     }  
  44.   
  45.     return;  
  46. }  

6. 求二叉树第K层的节点个数
递归解法:
(1)如果二叉树为空或者k<1返回0
(2)如果二叉树不为空并且k==1,返回1
(3)如果二叉树不为空且k>1,返回左子树中k-1层的节点个数与右子树k-1层节点个数之和
参考代码如下:

[cpp] view plain copy
 
 
 
  1. int GetNodeNumKthLevel(BinaryTreeNode * Root, int k)  
  2. {  
  3.     if(Root == NULL || k < 1)  
  4.         return 0;  
  5.     if(k == 1)  
  6.         return 1;  
  7.  int numLeft = GetNodeNumKthLevel(Root->Left, k-1); //左子树k-1层节点数  
  8.   int numRight = GetNodeNumKthLevel(Root->Right, k-1); //右子树k-1层节数  
  9.     return (numLeft + numRight);  
  10. }  

7. 求二叉树中叶子节点的个数
递归解法:
(1)如果二叉树为空,返回0
(2)如果二叉树不为空且左右子树为空,返回1
(3)如果二叉树不为空,且左右子树不同时为空,返回左子树中叶子节点个数加上右子树中叶子节点个数
参考代码如下:

[cpp] view plain copy
 
 
 
  1. int GetLeafNodeNum(BinaryTreeNode * Root)  
  2. {  
  3.     if(Root == NULL)  
  4.         return 0;  
  5.     if(Root->Left == NULL && Root->Right == NULL)  
  6.         return 1;  
  7.     int numLeft = GetLeafNodeNum(Root->Left);   // 左子树中叶节点的个数  
  8.     int numRight = GetLeafNodeNum(Root->Right);  // 右子树中叶节点的个数  
  9.     return (numLeft + numRight);  
  10. }  

8. 判断两棵二叉树是否结构相同
不考虑数据内容。结构相同意味着对应的左子树和对应的右子树都结构相同。
递归解法:
(1)如果两棵二叉树都为空,返回真
(2)如果两棵二叉树一棵为空,另一棵不为空,返回假
(3)如果两棵二叉树都不为空,如果对应的左子树和右子树都同构返回真,其他返回假
参考代码如下:

[cpp] view plain copy
 
 
 
  1. bool StructureCmp(BinaryTreeNode * Root1, BinaryTreeNode * Root2)  
  2. {  
  3.   if(Root1 == NULL && Root2 == NULL) // 都为空,返回真  
  4.        return true;  
  5.   else if(Root1 == NULL || Root2 == NULL) //有一个为空一个不为空,返回假  
  6.       return false; 
  7.  
  8. bool resultLeft = StructureCmp(Root1->Left,Root2->Left);//比较对应左子树   
  9. bool resultRight = StructureCmp(Root1->Right, Root2->Right);//比较对应右子
  10.     return (resultLeft && resultRight);  
  11. }   

9. 判断二叉树是不是平衡二叉树
递归解法:
(1)如果二叉树为空,返回真
(2)如果二叉树不为空,如果左子树和右子树都是AVL树并且左子树和右子树高度相差不大于1,返回真,其他返回假

参考代码:

解法一:

 

  1. bool IsBalanced(BinaryTreeNode* Root)  
  2. {  
  3.     if(Root== NULL)  
  4.         return true;  
  5.   
  6.     int LeftDepth = GetDepth(pRoot->Left);       //取深度
  7.     int RightDepth = GetDepth(pRoot->Right);  
  8.     int diff = RightDepth-LeftDepth;  
  9.   
  10.     if (diff>1 || diff<-1)  
  11.         return false;  
  12.   
  13.     return IsBalanced(Root->Left) && IsBalanced(Root->Right);  
  14. }  

 

 

[cpp] view plain copy
 
 
 
  1. bool IsAVL(BinaryTreeNode * Root, int & height)  
  2. {  
  3.     if(Root == NULL) // 空树,返回真  
  4.     {  
  5.         height = 0;  
  6.         return true;  
  7.     }  
  8.     int heightLeft;
  9.     bool resultLeft = IsAVL(Root->Left, heightLeft);   //判断左子树是否为AVL
  10.     int heightRight;  
  11.     bool resultRight = IsAVL(Root->Right, heightRight);    //判断右子树是否为AVL

  12.     //左子树和右子树都是AVL,并且高度相差不大于1,返回真  
  13.     if(resultLeft && resultRight && abs(heightLeft - heightRight) <= 1) //                        
  14.     {  
  15.         height = max(heightLeft, heightRight) + 1;  
  16.         return true;  
  17.     }  
  18.     else    
  19.            return false;  
  20.     }  
  21. }  

10. 求二叉树的镜像
递归解法:
(1)如果二叉树为空,返回空
(2)如果二叉树不为空,求左子树和右子树的镜像,然后交换左子树和右子树

参考代码如下:

 

void getImage(BinaryTreeNode *root)
{
    if(root != NULL && root->Left != NULL && root->Right != NULL)
    {
        BinaryTreeNode *temp = root->Left;        //交换左右子树
                  root->Left = root->Right;
                 root->Right = temp;
        getImage(root->Left);       //递归求解
        getImage(root->Right);
    }
}

 

 

[cpp] view plain copy
 
 
 
  1. BinaryTreeNode * Mirror(BinaryTreeNode * Root)  
  2. {  
  3.     if(pRoot == NULL) // 返回NULL  
  4.         return NULL;  
  5.     BinaryTreeNode * pLeft = Mirror(Root->Left); // 求左子树镜像  
  6.     BinaryTreeNode * pRight = Mirror(Root->Right); // 求右子树镜像  
  7.                             // 交换左子树和右子树  
  8.     Root->Left = pRight;  
  9.     Root->Right = pLeft;  
  10.     return Root;  
  11. }  

11. 求二叉树中两个节点的最低公共祖先节点
递归解法:
(1)如果两个节点分别在根节点的左子树和右子树,则返回根节点
(2)如果两个节点都在左子树,则递归处理左子树;如果两个节点都在右子树,则递归处理右子树

参考代码如下:

 

  1. BTreeNode *GetCommon( BTreeNode *Root, BTreeNode *Node1, BTreeNode *Node2){  
  2.     if( Root == NULL ) //说明是空树,不用查找了,也就找不到对应节点,则返回NULL  
  3.         return  NULL;  
  4.   
  5.     if( Root == Node1 || Root == Node2 )//说明在当前子树的根节点上找到两个节点之一  
  6.         return pRoot;  
  7.   
  8. BTreeNode *Left = GetCommon( Root->Left, Node1, Node2); //左子树中的查找两个节点并返回查找结果  
  9. BTreeNode *Right = GetCommon( Root->Right, Node1, Node2);//右子树中查找两个节点并返回查找结果  
  10.   
  11.     if( Left == NULL )//如果在左子树中没有找到,则断定两个节点都在右子树中,可以返回右子树中查询结果;
  12.          return Right;                              否则,需要结合左右子树查询结果共同断定  
  13.         
  14.     if ( Right == NULL )//如果在右子树中没有找到,则断定两个节点都在左子树中,可以返回左子树中查询结果;           return Left;                           否则,需要结合左右子树查询结果共同断定  
  15.         
  16.       
  17.     return Root;   //如果在左右子树中都找两个节点之一,则pRoot就是最低公共祖先节点,返回即可。  

 

 

递归解法效率很低,有很多重复的遍历,下面看一下非递归解法。

非递归解法:
先求从根节点到两个节点的路径,然后再比较对应路径的节点就行,最后一个相同的节点也就是他们在二叉树中的最低公共祖先节点
参考代码如下:

[cpp] view plain copy
 
 
 
  1. bool GetNodePath(BinaryTreeNode * pRoot, BinaryTreeNode * pNode,   
  2.                  list<BinaryTreeNode *> & path)  
  3. {  
  4.     if(pRoot == pNode)  
  5.     {     
  6.         path.push_back(pRoot);  
  7.         return true;  
  8.     }  
  9.     if(pRoot == NULL)  
  10.         return false;  
  11.     path.push_back(pRoot);  
  12.     bool found = false;  
  13.     found = GetNodePath(pRoot->m_pLeft, pNode, path);  
  14.     if(!found)  
  15.         found = GetNodePath(pRoot->m_pRight, pNode, path);  
  16.     if(!found)  
  17.         path.pop_back();  
  18.     return found;  
  19. }  
  20. BinaryTreeNode * GetLastCommonParent(BinaryTreeNode * pRoot, BinaryTreeNode * pNode1, BinaryTreeNode * pNode2)  
  21. {  
  22.     if(pRoot == NULL || pNode1 == NULL || pNode2 == NULL)  
  23.         return NULL;  
  24.     list<BinaryTreeNode*> path1;  
  25.     bool bResult1 = GetNodePath(pRoot, pNode1, path1);  
  26.     list<BinaryTreeNode*> path2;  
  27.     bool bResult2 = GetNodePath(pRoot, pNode2, path2);  
  28.     if(!bResult1 || !bResult2)   
  29.         return NULL;  
  30.     BinaryTreeNode * pLast = NULL;  
  31.     list<BinaryTreeNode*>::const_iterator iter1 = path1.begin();  
  32.     list<BinaryTreeNode*>::const_iterator iter2 = path2.begin();  
  33.     while(iter1 != path1.end() && iter2 != path2.end())  
  34.     {  
  35.         if(*iter1 == *iter2)  
  36.             pLast = *iter1;  
  37.         else  
  38.             break;  
  39.         iter1++;  
  40.         iter2++;  
  41.     }  
  42.     return pLast;  
  43. }  


在上述算法的基础上稍加变化即可求二叉树中任意两个节点的距离了。
12. 求二叉树中节点的最大距离

最大距离的两个点有可能出现在三种情况下

 

  1. 左子树
  2. 右子树
  3. 过节点x

 

经分析得出以下特点

  1. 以上三种情况最终必定一叶子结束
  2. 在第三种情况下必然是左子树高度 与 右子树高度 之和(只有这样,才可能取得最大值)

经过以上分析即可得出递推式

Dis(x) = max(Dis(x->left), Dis(x->right), height(x->left)+height(x->right))

参考代码

复制代码
int treeDistance(BiTree root)
{
    if(root == NULL)
        return 0;
    else if(root->left == NULL && root->right == NULL)
        return 0;
    int maxDis = 0;
    int dis = max(height(root->left) + height(root->right), 
                  treeDistance(root->left), 
                  treeDistance(root->right));
    if(maxDis < dis)
        maxDis = dis;
    return dis;
}
复制代码

这里用了一个技巧:maxDis是个全局变量,递归一次根节点会遍历到每个节点,在这期间于maxDis比较,从而得出了最大值,而不需要额外的空间。


13. 由前序遍历序列和中序遍历序列重建二叉树
二叉树前序遍历序列中,第一个元素总是树的根节点的值。中序遍历序列中,左子树的节点的值位于根节点的值的左边,右子树的节点的值位
于根节点的值的右边。
递归解法:
(1)如果前序遍历为空或中序遍历为空或节点个数小于等于0,返回NULL。
(2)创建根节点。前序遍历的第一个数据就是根节点的数据,在中序遍历中找到根节点的位置,可分别得知左子树和右子树的前序和中序遍
历序列,重建左右子树。

[cpp] view plain copy
 
 
 
  1. BinaryTreeNode * RebuildBinaryTree(int* PreOrder, int* InOrder, int nodeNum)  
  2. {  
  3.     if(PreOrder == NULL || InOrder == NULL || nodeNum <= 0)  
  4.         return NULL;  
  5.     BinaryTreeNode * Root = new BinaryTreeNode;  
  6.     // 前序遍历的第一个数据就是根节点数据  
  7.     Root->Value = PreOrder[0];  
  8.     Root->Left = NULL;  
  9.     Root->Right = NULL;  
  10.     // 查找根节点在中序遍历中的位置,中序遍历中,根节点左边为左子树,右边为右子树  
  11.     int rootPositionInOrder = -1;  
  12.     for(int i = 0; i < nodeNum; i++)  
  13.         if(InOrder[i] == Root->Value)  
  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 * PreOrderLeft = PreOrder + 1;  
  25.     int * InOrderLeft = InOrder;  
  26.     Root->Left = RebuildBinaryTree(PreOrderLeft, InOrderLeft, nodeNumLeft);  
  27.     // 重建右子树  
  28.     int nodeNumRight = nodeNum - nodeNumLeft - 1;  
  29.     int * PreOrderRight = PreOrder + 1 + nodeNumLeft;  
  30.     int * InOrderRight = InOrder + nodeNumLeft + 1;  
  31.     Root->Right = RebuildBinaryTree(PreOrderRight, InOrderRight, nodeNumRight);  
  32.     return Root;  
  33. }  

同样,有中序遍历序列和后序遍历序列,类似的方法可重建二叉树,但前序遍历序列和后序遍历序列不同恢复一棵二叉树,证明略。
14.判断二叉树是不是完全二叉树

 算法思想:采用层次遍历的算法,将所有节点都加入队列(包括空节点)。当遇到空节点时,查看其后是否有非空节点,若有,则不是完全二叉树。 

 

  1. bool is_complete(tree *root)  
  2. {  
  3.     queue Q;  
  4.     tree *p;  
  5.                     // 进行广度优先遍历(层次遍历),并把NULL节点也放入队列  
  6.     Q.push(root);  
  7.     while ((p = Q.pop()) != NULL)  
  8.     {  
  9.         Q.push(p->left);  
  10.         Q.push(p->right);  
  11.     }  
  12.   
  13.     // 判断是否还有未被访问到的节点  
  14.    while (!Q.is_empty())  
  15.     {  
  16.         p = Q.pop();  
  17.           
  18.          // 有未访问到的的非NULL节点,则树存在空洞,为非完全二叉树  
  19.         if (p != NULL)  
  20.         {  
  21.             return false;  
  22.         }  
  23.     }  
  24.   
  25.     return true;  

 

15 交换二叉树的左右儿子(即镜像)

交换二叉树的左右儿子,可以先交换根节点的左右儿子节点,然后递归以左右儿子节点为根节点继续进行交换。树中的操作有先天的递归性。。

复制代码
 1 //交换二叉树的左右儿子
 2 void BinTree::swap(BinTreeNode *root)
 3 {
 4     if(root == NULL)
 5     {
 6         return;
 7     }
 8     BinTreeNode *temp = root->left; 
 9            root->left = root->right;
10           root->right = temp;
11     swap(root->left);
12     swap(root->right);
13 }

非递归算法思想(使用队列):

1、根结点入队列,即放入列尾。

2、从队列中取出一个结点,即从队列头部取出一个元素。

3、将取出来的结点的左右儿子交换,然后依次放入队列尾部。

4、如果队列不为空,循环执行第2、3步。

16 判断一个节点是否在一颗子树中

可以和当前根节点相等,也可以在左子树或者右子树中。 

复制代码
 1 //判断一个节点t是否在以r为根的子树中
 2 bool BinTree::isContain(BinTreeNode *root,BinTreeNode *node)const
 3 {
 4     if(root== NULL)
 5     {
 6         return false;
 7     }
 8     else if(root == node)
 9     {
10         return true;
11     }
12     else
13     {
14         bool has = false;
15         if(root->left != NULL)
16         {
17             has = isContain(root->left, node);
18         }
19         if(!has && root->right != NULL)
20         {
21             has = isContain(root->right, node);
22         }
23         return has;
24     }
25 }
复制代码

17、判断是否为二叉查找树

 

    1. int IsSearchTree(const Bitree *root)  //递归遍历二叉树是否为二叉排序树  
    2. {  
    3.     if(root==NULL)         //空二叉树情况  
    4.         return 1;  
    5.     else if(!(root->lchild) && !(root->rchild))   //左右子树都无情况  
    6.         return 1;  
    7.     else if((root->lchild) && !(root->rchild))    //只有左子树情况  
    8.     {  
    9.         if(root->lchild->data > root->data)  
    10.             return 0;  
    11.         else  
    12.             return IsSearchTree(root->lchild);  
    13.     }  
    14.     else if((root->rchild) && !(root->lchild))   //只有右子树情况  
    15.     {  
    16.         if(root->rchild->data < root->data)  
    17.             return 0;  
    18.         else  
    19.             return IsSearchTree(root->rchild);  
    20.     }  
    21.     else         //左右子树全有情况  
    22.     {                                  
    23.         if((root->lchild->data > root->data) || (root->rchild->data < root->data))  
    24.             return 0;  
    25.         else  
    26.             return ( IsSearchTree(root->lchild) && IsSearchTree(root->rchild) );  
    27.     }  
    28. } 由于该算法只需要访问每个结点1次,因此时间复杂度为O(n)

18、给定有序数组,创建高度最小的二叉查找树

 

思路:   1 将数组中间位置的元素插入树中;

           2 将数组左半边元素插入左子树中;

           3 同理,右;

           4 递归处理

TreeNode createMinimalBST(int arr[], int start, int end)

{
    if (end < start)
   {
       return null;
    }
       int mid = start + (end - start) / 2;
   TreeNode root =new TreeNode(arr[mid]);
   root.left=createMinimalBST(arr,start,mid-1);
   root.right=createMinimalBST(arr,mid+1,end);
    return root;
}
TreeNode createMinimalBST(int array[])
{
return   createMinimalBST(array,0,array.length-1);

}

 

19、已知二叉树的前序遍历和中序遍历,输出后序遍历的代码

 

  1. void BinaryTreeFromOrderings(char* inorder, char* preorder, int length)  
  2. {  
  3.   if(length == 0)  
  4.     {  
  5.       return;  
  6.     }  
  7.   char node_value = *preorder;  
  8.   int rootIndex = 0;  
  9.   for(;rootIndex < length; rootIndex++)  
  10.     {  
  11.       if(inorder[rootIndex] == *preorder)  
  12.       break;  
  13.     }  
  14.   
  15. BinaryTreeFromOrderings(inorder, preorder +1, rootIndex);    //Left   and  Right
  16.  
  17. BinaryTreeFromOrderings(inorder + rootIndex + 1, preorder + rootIndex + 1, length - (rootIndex + 1));             
  18.   cout<<node_value<<endl;  
  19.   return;  
  20. }  
  21. //来自: http://blog.csdn.net/feliciafay/article/details/6816871

 

 

===============

创建二叉树:

 

void CreateBinaryTree(BinaryTreeNode * &root)
{

    char ch;
    cin>>ch;
    if(ch=='#')     //当遇到#时,令树的根节点为NULL,从而结束该分支的递归 
        root = NULL;
    else 
    {
         root=new BinaryTreeNode;
         root->data=ch;

         CreateBinaryTree(root->left);
         CreateBinaryTree(root->right);
    }
}
Status CreateBiTree(Binary_Tree &Root)
{
    char ch;
   
Root=(Binary_Tree)malloc(sizeof(BiTree));
    if(!Root)
        exit(OVERFLOW);
    cin>>ch;
    if(ch=='0')
        Root=NULL;
    else
    {
        Root->data=ch;
        CreateBiTree(Root->Lchild);
        CreateBiTree(Root->Rchild);
   }
   return OK;
}

 

posted @ 2018-05-20 15:53  道微真理  阅读(244)  评论(0编辑  收藏  举报