题目:输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设前序遍历与中序遍历的结果都不含重复的数字。
eg:前序遍历:{1,2,4,7,3,5,6,8};
中序遍历:{4,7,2,1,5,3,8,6};
二叉树结点定义如下:
struct BinaryTreeNode
{
int _value;
BinaryTreeNode* _left;
BinaryTreeNode* _right;
}
{
int _value;
BinaryTreeNode* _left;
BinaryTreeNode* _right;
}
c++实现函数说明:
本题的函数主要是有参构造函数:BinaryTree(int* pre, int* inOrder, int len);
有参构造函数调用函数:BinaryTreeNode* _CreateBinaryTree(BinaryTreeNode*& root,int*& pre, int*& inOrder, int len);
此函数又调用了主要函数:BinaryTreeNode* _RealCreateTree(BinaryTreeNode*& root,int* startPre, int* endPre, int* startIn, int* endIn);
函数void _DestoryBinaryTree(BinaryTreeNode*& root);:递归销毁一棵树;
分析如下:
1.先根据先序遍历创建出根结点:root;
2.再通过中序遍历找出根结点,用根结点的下标计算出左子树的个数;
3.再通过左子树的个数计算出在先序遍历中左子树结尾的位置;
4.通过以上计算,我们已经将二叉树分为左子树和右子树,然后大问题化作小问题;
5.遍历左子树;
6.遍历右子树;
依据上面的思路构建出的二叉树如上图:
代码如下:
#include<iostream>
using namespace std;
struct BinaryTreeNode
{
int _value;
BinaryTreeNode* _left;
BinaryTreeNode* _right;
BinaryTreeNode(int value = 0)
:_value(value),_left(NULL), _right(NULL)
{}
};
class BinaryTree
{
public:
BinaryTree()
:root(NULL)
{}
BinaryTree(int* pre, int* inOrder, int len)
{
_CreateBinaryTree(root, pre, inOrder, len);
}
~BinaryTree()
{
_DestoryBinaryTree(root);
}
private:
void _DestoryBinaryTree(BinaryTreeNode*& root)
{
if (root)
{
BinaryTreeNode* tmp = root;
if (tmp->_left)
{
_DestoryBinaryTree(tmp->_left);
}
if (tmp->_right)
{
_DestoryBinaryTree(tmp->_right);
}
delete[] tmp;
tmp = NULL;
}
}
BinaryTreeNode* _CreateBinaryTree(BinaryTreeNode*& root,int*& pre, int*& inOrder, int len)
{
if (pre == NULL || inOrder == NULL || len <= 0)
{
return NULL;
}
return _RealCreateTree(root, pre, pre + len - 1, inOrder, inOrder + len - 1);
}
BinaryTreeNode* _RealCreateTree(BinaryTreeNode*& root,int* startPre, int* endPre, int* startIn, int* endIn)
{
int rootValue = startPre[0];
root = new BinaryTreeNode(rootValue);
//1.有一个结点
if (startPre == endPre)
{
if (startIn == endIn && *startPre == *startIn)
{
return root;
}
else
{
cout << "preOrder and InOder is not matching" << endl;
return NULL;
}
}
//2.有多个结点
int* rootIn = startIn;
while (rootIn < endIn && *rootIn != root->_value)
{
++rootIn;
}
if (rootIn == endIn && *rootIn != root->_value)
{
cout << "preOrder and InOder is not matching" << endl;
return NULL;
}
//1.通过中序遍历计算左子树的节点个数leftLen
//2.通过计算出的左子树个数,再计算先序遍历中的左子树中的最后一个节点位置preLeftOfend
int leftLen = rootIn - startIn;
int* preLeftOfend = startPre + leftLen;
//构建左子树
if (leftLen > 0)
{
_RealCreateTree(root->_left, startPre + 1, preLeftOfend, startIn, rootIn - 1);
}
//构建右子树
if (leftLen < endPre - startPre)
{
_RealCreateTree(root->_right, preLeftOfend + 1, endPre, rootIn + 1, endIn);
}
return root;
}
private:
BinaryTreeNode* root;
};
void Test()
{
int pre[] = { 1, 2, 4, 7, 3, 5, 6, 8 };
int in[] = { 4, 7, 2, 1, 5, 3, 8, 6 };
int len = sizeof(pre) / sizeof(pre[0]);
BinaryTree bt(pre, in, len);
}
void Test2()
{
int pre[] = { 1, 2, 4, 8, 9, 5, 3, 6, 7 };
int in[] = { 8, 4, 9, 2, 5, 1, 6, 3, 7 };
int len = sizeof(pre) / sizeof(pre[0]);
BinaryTree bt(pre, in, len);
}
void Test3()
{
int pre[] = { 1, 2, 3, 4, 5, 6 };
int in[] = { 6, 5, 4, 3, 2, 1 };
int len = sizeof(pre) / sizeof(pre[0]);
BinaryTree bt(pre, in, len);
}
void Test4()
{
int pre[] = { 1, 2, 3, 4, 5, 6 };
int in[] = { 1, 2, 3, 4, 5, 6 };
int len = sizeof(pre) / sizeof(pre[0]);
BinaryTree bt(pre, in, len);
}
void Test5()
{
int pre[] = { 10 };
int in[] = { 10 };
int len = sizeof(pre) / sizeof(pre[0]);
BinaryTree bt(pre, in, len);
}
void Test6()
{
int pre[] = { 1,2,3,4,5};
int in[] = {4,5,7,3,1};
int len = sizeof(pre) / sizeof(pre[0]);
BinaryTree bt(pre, in, len);
}
int main()
{
//1.普通二叉树:Test():不完全二叉树;
// Test2():完全二叉树;
//2.特殊二叉树:Test3():所有结点没有右结点;
// Test4():所有结点没有左节点;
// Test5():只有一个结点;
//3.特殊测试: Test6():输入的前序与中序不匹配;
Test();
Test2();
Test3();
Test4();
Test5();
Test6();
return 0;
}
除Test6()外,所有测试都可以通过调试去看构造出的二叉树结构;
Test6()测试不匹配的结果如下图所示: