来源:《剑指Offer》
题目:输入某二叉树先序和中序遍历的结果,请重建出该二叉树。假设输入的先序和中序遍历结果中不含重复数字。例如:输入先序遍历{1,2,4,7,3,5,6,8}和中序遍历{4,7,2,1,5,3,8,6},则重建出二叉树并输出它的头结点。
分析:先序遍历的第一个结点就是二叉树的根结点,然后到中序遍历中找这个根结点,在中序遍历中,根结点左边的是左子树,右边的是右子树。再到先序遍历中读第二个结点,就是左子树的根结点。利用递归,继续在左子树中寻找左子树的根结点……左子树找完了找右子树。
算法思想很简单,很容易看出递归来,但要把代码写完整不容易,需要把思路整理清楚。
代码(C++):
#include<iostream>
using namespace std;
struct BinaryTreeNode{
int value;
BinaryTreeNode *lChild;
BinaryTreeNode *rChild;
};
BinaryTreeNode * CreateBinaryTree(int * startPreOrder,int *endPreOrder, int * startInOrder,int *endInOrder)
{
// 只有一个节点
if((startPreOrder == endPreOrder)&&(startInOrder == endInOrder))
{
if(*startPreOrder != *startInOrder)
{
cout<<"wrong input 2"<<endl;
return NULL;
}
BinaryTreeNode * node = new BinaryTreeNode();
node->value = *startPreOrder;
node->lChild = NULL;
node->rChild = NULL;
return node;
}
// 从preOrder中找到根元素
int rootValue = startPreOrder[0];
BinaryTreeNode * root = new BinaryTreeNode();
root->value = rootValue;
root->lChild = root->rChild = NULL;
// 在中序中找根元素
int *inOrder = startInOrder;
while((inOrder <= endInOrder) && (*inOrder != rootValue) )
{
inOrder++;
}
// 中序中找不到根元素
if(*inOrder != rootValue)
{
cout<<"wrong input 3"<<endl;
return NULL;
}
// 确定左右子树长度
int leftChildLen = inOrder-startInOrder;
// 确定左右子树在先序数组中的起始位置和终止位置
int *leftChildPreEnd = startPreOrder+leftChildLen;
// 寻找左子树的根,作为根节点的左孩子
if(leftChildLen > 0)
root->lChild = CreateBinaryTree(startPreOrder+1,leftChildPreEnd, startInOrder,inOrder-1);
// 寻找右子树的根,作为根节点的右孩子
if(leftChildPreEnd < endPreOrder)
root->rChild = CreateBinaryTree(leftChildPreEnd+1,endPreOrder, inOrder+1,endInOrder);
return root;
}
BinaryTreeNode * Create(int * preOrder,int * inOrder,int length)
{
if(preOrder==NULL||inOrder==NULL||length<=0)
{
cout<<"wrong input 1"<<endl;
return NULL;
}
// 调用递归方法
return CreateBinaryTree(preOrder, preOrder + length - 1, inOrder,inOrder + length - 1);
}
void PreOrderPrint(BinaryTreeNode * root)
{
if(root == NULL)
{
return;
}
cout<<root->value<<" ";
PreOrderPrint(root->lChild);
PreOrderPrint(root->rChild);
}
void InOrderPrint(BinaryTreeNode * root)
{
if(root ==NULL)
{
return;
}
if(root->lChild != NULL)
{
InOrderPrint(root->lChild);
}
cout<<root->value<<" ";
if(root->rChild != NULL)
{
InOrderPrint(root->rChild);
}
}
int main()
{
int PreOrder[8] = {1,2,4,7,3,5,6,8};
int InOrder[8] = {4,7,2,1,5,3,8,6};
BinaryTreeNode *root = Create(PreOrder,InOrder, 8);
cout<<"PreOrder: ";
PreOrderPrint(root);
cout<<endl;
cout<<"InOrder: ";
InOrderPrint(root);
return 0;
}