更多剑指offer面试习题请点击: 《剑指offer》(第二版)题集目录索引
题目:
输入某二叉树的前序遍历和中序遍历结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{ 1, 2, 4, 7, 3, 5, 6, 8 }
和中序遍历序列{ 4, 7, 2, 1, 5, 3, 8, 6 }
,则重建的二叉树如图所示:
解题思路:
我们知道前序遍历的第一个节点一定是这棵树的根节点,根据这个根节点和二叉树的树的中序遍历序列,可以得到这颗树的左子树、右子树。这样我们就确定了这颗树的根节点,那么根节点的左、右节点又如何确定呢?
这时候采用递归思想,把左右子树看作一棵完整的树,根据前序序列可以得到左右子树的根节点,也就是这颗树的根节点的左右孩子节点。就这样一直递归就能构建出这颗二叉树。
< code >
typedef struct BinaryTreeNode
{
struct BinaryTreeNode* _left;
struct BinaryTreeNode* _right;
int _data;
}BTNode;
/*
*功能:打印二叉树的前序遍历
*参数:root——二叉树的根节点
*返回值:无
*/
void BTreePrevOrder(BTNode* root) //前序遍历
{
if (NULL == root)
{
return;
}
printf("%d ", root->_data);
BTreePrevOrder(root->_left);
BTreePrevOrder(root->_right);
}
/*
*功能:创建节点
*参数:x——节点的值
*返回值:节点的地址
*/
BTNode* BuyBTNode(int x) //创建节点
{
BTNode* node = (BTNode*)malloc(sizeof(BTNode));
assert(node != NULL);
node->_left = NULL;
node->_right = NULL;
node->_data = x;
return node;
}
/*
*功能:递归构建二叉树
*参数:
pre_arry——前序遍历
pr_start——前序遍历开始的位置
pr_end ——前序遍历结束的位置
in_arry ——中序遍历
in_start——中序遍历开始的位置
in_end ——中序遍历结束的位置
*返回值:当前树的根节点地址
*/
BTNode* Reconstruction(int* pre_arry, int pr_start, int pr_end, int* in_arry, int in_start, int in_end)
{
if (pr_start > pr_end || in_start > in_end)
return NULL;
BTNode* root = BuyBTNode(pre_arry[pr_start]);
int i = in_start;
for (; i <= in_end; i++)
{
if (in_arry[i] == pre_arry[pr_start])
{
root->_left = Reconstruction(pre_arry, pr_start + 1, pr_start + i - in_start, in_arry, in_start, i - 1);
root->_right = Reconstruction(pre_arry, pr_start + i - in_start + 1, pr_end, in_arry, i + 1, in_end);
}
}
return root;
}
/*
*功能:重建二叉树
*参数:
pre_arry——前序遍历
in_arry ——中序遍历
length ——序列长度
*返回值:重建后的二叉树的根节点地址
*/
BTNode* ConstructBinaryTree(int* pre_arry, int* in_arry, int length) //重建二叉树
{
if (pre_arry == NULL || in_arry == NULL || length <= 0)
return NULL;
return Reconstruction(pre_arry, 0, length - 1, in_arry, 0, length - 1);
}
< 测试code >
/*
*功能:测试程序
*参数:
testName——测试名
pre_arry ——前序遍历
in_arry ——中序遍历
length_pr——前序遍历长度
length_in——中序遍历长度
*返回值:无
*/
void Test(char* testName, int* pre_arry, int* in_arry, int length_pr, int length_in)
{
if (length_pr != length_in)
{
return;
}
if (testName == NULL)
{
return;
}
printf("%s:\n", testName);
BTNode* root = ConstructBinaryTree(pre_arry, in_arry, length_pr);
printf("重建的二叉树的前序序列:");
BTreePrevOrder(root);
printf("\n");
printf("输入的二叉树的前序序列:");
if (pre_arry != NULL)
{
int i = 0;
for (; i < length_pr; ++i)
{
printf("%d ", pre_arry[i]);
}
}
printf("\n===============================================================\n\n");
}
//完全二叉树
void test1()
{
int pre_arry[] = { 1, 2, 4, 8, 5, 3, 6, 7 }; //前
int in_arry[] = { 8, 4, 2, 5, 1, 6, 3, 7 }; //中
int length_pr = sizeof(pre_arry) / sizeof(pre_arry[0]);
int length_in = sizeof(in_arry) / sizeof(in_arry[0]);
Test("test1",pre_arry, in_arry, length_pr, length_in);
}
//非完全二叉树
void test2()
{
int pre_arry[] = { 1, 2, 4, 5, 3, 7 }; //前
int in_arry[] = { 4, 2, 5, 1, 3, 7 }; //中
int length_pr = sizeof(pre_arry) / sizeof(pre_arry[0]);
int length_in = sizeof(in_arry) / sizeof(in_arry[0]);
Test("test2", pre_arry, in_arry, length_pr, length_in);
}
//所有节点都没有右节点的二叉树
void test3()
{
int pre_arry[] = { 1, 2, 3, 4, 5, 6 }; //前
int in_arry[] = { 6, 5, 4, 3, 2, 1 }; //中
int length_pr = sizeof(pre_arry) / sizeof(pre_arry[0]);
int length_in = sizeof(in_arry) / sizeof(in_arry[0]);
Test("test3", pre_arry, in_arry, length_pr, length_in);
}
//所有节点都没有左节点的二叉树
void test4()
{
int pre_arry[] = { 1, 2, 3, 4, 5, 6 }; //前
int in_arry[] = { 1, 2, 3, 4, 5, 6 }; //中
int length_pr = sizeof(pre_arry) / sizeof(pre_arry[0]);
int length_in = sizeof(in_arry) / sizeof(in_arry[0]);
Test("test4", pre_arry, in_arry, length_pr, length_in);
}
//只有一个节点的二叉树
void test5()
{
int pre_arry[] = { 1 }; //前
int in_arry[] = { 1 }; //中
int length_pr = sizeof(pre_arry) / sizeof(pre_arry[0]);
int length_in = sizeof(in_arry) / sizeof(in_arry[0]);
Test("test5", pre_arry, in_arry, length_pr, length_in);
}
//只有一个节点的二叉树
void test6()
{
int* pre_arry = NULL; //前
int* in_arry = NULL; //中
int length_pr = sizeof(pre_arry) / sizeof(pre_arry[0]);
int length_in = sizeof(in_arry) / sizeof(in_arry[0]);
Test("test6", pre_arry, in_arry, length_pr, length_in);
}
//前序序列和中序序列不匹配
void test7()
{
int pre_arry[] = { 1, 2, 4, 7, 3, 5, 6, 8 }; //前
int in_arry[] = { 4, 7, 2, 1, 6, 3, 8, 5 }; //中
int length_pr = sizeof(pre_arry) / sizeof(pre_arry[0]);
int length_in = sizeof(in_arry) / sizeof(in_arry[0]);
Test("test7", pre_arry, in_arry, length_pr, length_in);
}
运行截图: