【7】二叉树的重建

面试题7:重建二叉树

1、题目
2、分析
3、测试代码
4、测试结果如下
- 给出二叉树的前序遍历和中序遍历,或者后序遍历和中序遍历就可以构建出该二叉树;
- 若仅仅给出前序遍历和后序遍历无法构建出一颗二叉树

1、题目:

输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。
假设输入的前序遍历和中序遍历的结果中都不含重复的数字;

例如:
输入前序遍历序列{1, 2, 4, 7, 3, 5, 6, 8},
它的中序遍历序列{4, 7, 2, 1, 5, 3, 8, 6},
则重建出如下所示:
这里写图片描述

2、分析:

根据前序遍历序列我们可以得出,前序中第一个数字(1) 就是该树的根节点,那么,在中序遍历中,(1)为中间节点的位置,在(1)前面的所有数字为该树的左子树中的所有节点(4,7,2),在(1)右面的所有数字,为右子树的所有节点(5,3,8,6);再根据同样的方法寻求左右子树的节点;在前序遍历中(1)的左孩子为(2)那么,在中序遍历中,(2)的前面(4,7)为它左子树的节点,(2)的后面没有数字,所以(2)没有右孩子;在前序遍历中,(2)的左孩子为(4),在中序遍历中,(4)的前面没有数字,代表(4)没有左孩子,(4)的后面为(7),则(7)为(4)的右孩子,到这里,根节点(1)的左子树就全部构建完成,其右子树构建跟左子树的方式一样,这里不再赘述;

3、测试代码:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
 struct BinTreeNode
{
    int _value;
    BinTreeNode *_pLeft;
    BinTreeNode *_pRight;
};
//二叉树的基本操作
BinTreeNode* BuyBTNode(int data)//创建节点
{
    BinTreeNode* node = (BinTreeNode*)malloc(sizeof(BinTreeNode));
    node->_value = data;
    node->_pLeft = NULL;
    node->_pRight = NULL;
    return node;
}

void DestroyTree(BinTreeNode* root)//销毁二叉树
{
    if (root == NULL)
        return;
    DestroyTree(root->_pLeft);
    DestroyTree(root->_pRight);
    free(root);
}
//========================================================

BinTreeNode* constructcore( int*startpre, int* endpre, int*startin, int*endin )
{
    int rootvalue = startpre[0];
    BinTreeNode* root = new BinTreeNode();
    root->_value = rootvalue;
    root->_pLeft  = root->_pRight  = NULL;
    //只有根节点
    if(startpre == endpre )
    {
        if(startin == endin && *startpre == *startin)
        {
            return root;
        }
        else printf("无效的输入\n");
    }
    //在中序遍历中找到根节点的值
    int* rootin = startin;
    while(rootin <= endin && *rootin != rootvalue )
    {
        ++rootin;
    }
    if(rootin == endin &&*rootin!= rootvalue)
    {
        printf("无效的输入\n");
    }
    int leftlength = rootin - startin;
    int* leftPreEnd = startpre + leftlength;
    if(leftlength > 0)
    {
        //构建左子树
        root->_pLeft = constructcore(startpre+1,leftPreEnd,startin,rootin-1);
    }
    if(leftlength <( endpre -startpre) )
    {//构建右子树
        root->_pRight = constructcore(leftPreEnd+1,endpre,rootin+1,endin);
    }
    return root;
}


BinTreeNode* construct(int* pre,int* in , int length)
{
    if(pre == NULL || in == NULL||length <= 0)
    {
        return NULL;
    }
    return constructcore(pre, pre+length-1,in,in+length-1);
}

//=========================测试代码===========================
//************************************************************
//============================================================
void test(int* preorder,int* inorder,int length)
{
      printf("前序遍历为: ");
    for (int i = 0; i < length; ++i)
        printf("%d ", preorder[i]);
        printf("\n");

    printf("中序遍历为: ");
    for (int i = 0; i < length; ++i)
        printf("%d ", inorder[i]);
    printf("\n");
    BinTreeNode* root = construct(preorder, inorder, length);
    printf("\n");
    DestroyTree(root);
}
// 普通二叉树
//              1
//           /     \
//          2       3  
//         /       / \
//        4       5   6
//         \         /
//   
void Test1()
{
    const  int length = 8;
    int preorder[length] = { 1, 2, 4, 7, 3, 5, 6, 8 };
    int inorder[length] = { 4, 7, 2, 1, 5, 3, 8, 6 };
    test(preorder,inorder,length);
}
// 所有结点都没有右子结点
//            1
//           / 
//          2   
//         / 
//        3 
//       /
//      4
//     /
//    5
void Test2()
{
    const int length = 5;
    int preorder[length] = {1, 2, 3, 4, 5};
    int inorder[length] = {5, 4, 3, 2, 1};
    test(preorder,inorder,length);
}
// 所有结点都没有左子结点
//            1
//             \ 
//              2   
//               \ 
//                3 
//                 \
//                  4
//                   \
//                    5
void Test3()
{
    const int length = 5;
    int preorder[length] = {1, 2, 3, 4, 5};
    int inorder[length] = {1, 2, 3, 4, 5};
    test(preorder,inorder,length);
}
// 树中只有一个结点
void Test4()
{
    const int length = 1;
    int preorder[length] = {1};
    int inorder[length] = {1};

    test(preorder,inorder,length);
}

// 完全二叉树
//              1
//           /     \
//          2       3  
//         / \     / \
//        4   5   6   7
void Test5()
{
    const int length = 7;
    int preorder[length] = {1, 2, 4, 5, 3, 6, 7};
    int inorder[length] = {4, 2, 5, 1, 6, 3, 7};

    test(preorder,inorder,length);
}

int main()
{
    Test1();
    Test2();
    Test3();
    Test4();
    Test5();

    return 0;
}

4、测试结果如下:

这里写图片描述

猜你喜欢

转载自blog.csdn.net/dai_wen/article/details/79948798