解本题首先要明确中序遍历和前序遍历的定义,我们可以先根据前序遍历在中序遍历中找到根节点,然后位于中序遍历中根节点左边的就是此根节点对应的左子树,位于中序遍历中根节点右边的就是此根节点对应的右子树,由此产生递归的思路,每次先在前序遍历中找到根节点,然后在中序遍历中确定左子树和右子树,接着递归生成根节点的左子树和右子树即可:
#include <iostream>
struct BTN //二叉树结点结构
{
int value;
BTN* pleft;
BTN* pright;
};
int find_pos(int value, int * mid, int mid_head, int mid_tail){//前序遍历的值value(即根结点)在中序遍历中的位置,用以划分左右子树,mid_head、mid_tail指示当前中序遍历数组范围
int count = 0;
for (int i = mid_head ; i <= mid_tail ; i++,count++)
{
if (mid[i] == value)
break;
}
return count;
}
void build_tree(BTN** root , int* pre , int pre_head , int pre_tail , int* mid , int mid_head , int mid_tail)//根据前序遍历pre[pre_head:pre_tail]和中序遍历mid[mid_head:mid_tail]递归生成左右子树
{
if (pre_head <= pre_tail&& mid_head<=mid_tail) //边界条件
{
*root = new BTN();
(*root)->pleft = nullptr;
(*root)->pright = nullptr;
(*root)->value = pre[pre_head];
int pos = find_pos(pre[pre_head], mid, mid_head, mid_tail);
build_tree(&((*root)->pleft), pre, pre_head + 1, pre_head +pos,mid,mid_head, mid_head + pos - 1);//左子树的前、中遍历数组
build_tree(&((*root)->pright), pre,pre_head + pos + 1, pre_tail, mid, mid_head + pos+1, mid_tail); //右子树的前、中遍历数组
}
}
BTN* rebuild_BT(int* pre, int * mid, int len)//重建二叉树
{
if (len <= 0)
return nullptr;
BTN* phead = nullptr; //头节点指针
build_tree(&phead, pre, 0, len - 1, mid, 0, len - 1);//因为要改变头节点指针,因此需要传一个二级指针,
return phead;
}
void print_bt(BTN* root)//递归前序打印树
{
if (root!=nullptr)
{
std::cout << root->value << " ";
print_bt(root->pleft);
print_bt(root->pright);
}
}
int main()
{
int pre[] = { 1, 2, 4, 7, 3, 5, 6, 8 };
int mid[] = { 4,7,2,1,5,3,8,6 };
BTN* phead = rebuild_BT(pre, mid, 8);
print_bt(phead);
system("pause");
}