剑指offer重构二叉树超详细讲解

剑指offer重构二叉树超详细讲解

题目:输入某二叉树的前序遍历和中序遍历的结果,请重构该二叉树,假设输入的前序遍历和中序遍历的结果不含重复的数字。例如
前序遍历{1,2,4,7,3,5,6,8}
中序遍历{4,7,2,1,5,3,8,6}

显然此二叉树应该为

    ///              1
    ///           /     \
    ///          2       3  
    ///         /       / \
    ///        4       5   6
    ///         \         /
    ///          7       8  

前序遍历序列的第一个数字1就是根节点。扫描中序遍历,就能确定根节点的位置。
根据中序遍历的特点:
在根节点前面的数字4 7 2都是左子树节点的值
在根节点1后面的数字5 3 8 6都是右子树的值

在这里插入图片描述
我们可以用递归的方法去完成重构二叉树
我们先根据前序遍历的第一个数字创建根节点,接下里在中序遍历序列找到根节点位置,这样能确定左右子树节点数量。这样就能递归调用分别取构建他们的左右子树。
过程如下:

  1. Pre 1 2 4 7 3 5 6 8
    Ord 4 7 2 1 5 3 8 6
    将根节点1分成 左树4 7 2 和 右数 5 3 8 6

  2. 构建1的左子树
    Pre 2 4 7
    Ord 4 7 2
    构建2的左子树
    Pre 4 7
    Ord 4 7
    构建4的右子树
    Pre 7
    Ord 7
    根节点4右树构建完成
    中序遍历结果 4 7
    根节点2左树构建完成
    中序遍历结果 4 7 2
    根节点1左树构建完成

  3. 构建1的右子树
    Pre 3 5 6 8
    Ord 5 3 8 6
    构建3的左子树
    Pre 5
    Ord 5
    3节点左树完成
    中序遍历结果 5 3
    构建3的右子树
    Pre 6 8
    Ord 8 6
    构建6的左子树
    Pre 8
    Ord 8
    根节点6左树构建完成
    中序遍历结果 8 6
    根节点3右树构建完成
    中序遍历结果 5 3 8 6
    根节点1右树构建完成
    中序遍历结果 4 7 2 1 5 3 8 6

树已创造完成。下面上代码:

#include<bits/stdc++.h>
using namespace std;

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

void print(BTNode* head)
{
 if(head==NULL)return;
 print(head->left);
 cout<<head->value<<" ";
 print(head->right);
}

BTNode* ConstructCore
(int* startPre,int* endPre,int* startOrd,int* endOrd)
{
 cout<<" 开始  前序遍历区间"<<*startPre<<"->"<<*endPre<<"  ||  中序遍历区间"<<*startOrd<<"->"<<*endOrd<<endl;
 //前序遍历的第一个数字就是根节点 
 int rootvalue=startPre[0];
 BTNode* root=new BTNode();
 root->value=rootvalue;
 root->left=root->right=NULL;
 //如果只有一个节点就返回 
 if(startPre==endPre)
 {
   return root;
 }
 //中序遍历找到根节点的位置,其左为左子树,右为右子树 
 int* rootoder=startOrd;
 while(rootoder<=endOrd&&*rootoder!=rootvalue)
 rootoder++;
  
 
 int leftLenth=rootoder-startOrd;//左子树总长度 
 int* leftPreend=startPre+leftLenth;//左子树末尾 
 if(leftLenth>0)
 {
  cout<<"构建左子树:"; 
  root->left= ConstructCore(startPre+1,leftPreend,startOrd,rootoder-1);
 }
 if(leftLenth<endPre-startPre)
 {
  cout<<"构建右子树:"; 
  root->right=ConstructCore(leftPreend+1,endPre,rootoder+1,endOrd);
 }
 cout<<"中序遍历root:"; 
 print(root);
 cout<<endl;
 return root;
}

BTNode* Construct(int* preoder,int* inorder,int lenth)
{
  cout<<"重建二叉树:"; 
 return ConstructCore(preoder,preoder+lenth-1,inorder,inorder-1+lenth);
}
int main()
{ 
 int pre[8]={1,2,4,7,3,5,6,8};
 int ord[8]={4,7,2,1,5,3,8,6};
 cout<<"前序遍历为:1 2 4 7 3 5 6 8"<<endl;
 cout<<"中序遍历为:4 7 2 1 5 3 8 6"<<endl;
 BTNode* head=Construct(pre,ord,8);
  return 0;
}




代码运行结果:

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/bwabdbkjdbkjwabd/article/details/108325737