剑指offer--面试题6 重建二叉树

根据先序遍历和中序遍历还原二叉树


1.二叉树先序遍历的第一个结点必定是根节点,所以可以在中序遍历中确定根节点的位置。

2.中序遍历中,根节点之前的结点都是二叉树的左子树,之后的都是二叉树的右子树。可以得到左子树的结点个数m和右子树的结点个数n。

3.同时,先序遍历中,根节点之后的m个结点都是二叉树的左子树。

4.这是重复上面3个步骤,构建左右子树,用递归方法完成。


#include <iostream>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <cstdio>

using namespace std;

struct BinaryTreeNode
{
    int value;
    BinaryTreeNode *left;
    BinaryTreeNode *right;
};

//递归寻找结点
BinaryTreeNode * BuildRecursivly(int *preStart,int *preEnd,int *inStart,int *inEnd)
{
     //在先序遍历序列中取出第一个元素即为根节点元素
    int value = preStart[0];
    //printf("value:%d,preStart:%d,preEnd:%d,inStart:%d,inEnd:%d\n",value,*preStart,*preEnd,*inStart,*inEnd);
    //构造根节点
    BinaryTreeNode *root = new BinaryTreeNode();
    root->value=value;
    root->left=NULL;
    root->right=NULL;
    //递归结束的情况,即只剩一个叶子节点
    if(preStart == preEnd)
    {
        if(inStart == inEnd && (*preStart == *inStart))
        {
            //printf("node:%d,left:%d,right:%d\n",root->value,root->left,root->right);
            return root;
        }
        else
        {
            throw exception();
        }
    }
    //在中序遍历序列中找出根节点的位置
    int *inorder=inStart;
    while(inorder <= inEnd && *inorder != value)
    {
        inorder++;
    }
    if(inorder == inEnd && *inorder != value)
    {
        throw exception();
    }
    //取得左子树的长度以及在先序遍历中取得右子树的起始位置
    int leftTreeLen = inorder - inStart;
    int *preLeftEnd = preStart + leftTreeLen;
    //如果左子树存在,则递归左子树
    if(leftTreeLen > 0)
        root->left=BuildRecursivly(preStart+1,preLeftEnd,inStart,inorder-1);
    //如果右子树存在,则递归右子树
    if((preEnd - preStart) > leftTreeLen)
        root->right=BuildRecursivly(preLeftEnd+1,preEnd,inorder+1,inEnd);
    return root;
}

//创建二叉树
BinaryTreeNode *BulidBinaryTree(int *szPrevOrder, int *szInOrder, int length)
{
    if(szPrevOrder==NULL||szInOrder==NULL)  return NULL;
    return BuildRecursivly(szPrevOrder, szPrevOrder+length-1, szInOrder, szInOrder+length-1);
}

void preOrder(BinaryTreeNode *root)//先序遍历
{
    if(root!=NULL)
    {
        //根
        printf("%d ",root->value);
        //左子树
        preOrder(root->left);
        //右子树
        preOrder(root->right);
    }
}

void InOrder(BinaryTreeNode *root)//中序遍历
{
    if(root!=NULL)
    {
        //左子树
        preOrder(root->left);
        //根
        printf("%d ",root->value);
        //右子树
        preOrder(root->right);
    }
}

void postOder(BinaryTreeNode *root)
{
    if(root!=NULL)
    {
        //左子树
        preOrder(root->left);
        //右子树
        preOrder(root->right);
        //根
        printf("%d ",root->value);
    }
}

int main()
{
    int szPrevOrder[] = {1, 2, 4, 7, 3, 5, 6, 8};   //二叉树的先序遍历
    int szInOrder[] = {4, 7, 2, 1, 5, 3, 8, 6};     //二叉树的中序遍历
    int length = sizeof(szPrevOrder)/sizeof(int);
    BinaryTreeNode *root = BulidBinaryTree(szPrevOrder,szInOrder,length);
    cout<<"PrevOrder: ";
    preOrder(root);
    cout<<endl<<"InOrder:   ";
    InOrder(root);
    cout<<endl<<"PostOrder: ";
    postOder(root);
    cout<<endl;

    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值