题目 :输入某二叉树的前序遍历和中序遍历结果,请重建出该二叉树。
假设输入的前序遍历和中序遍历的结果都不含重复的数字。
思路:在二叉树的前序遍历序列中,第一个数字总是树的根节点的值。但在中序遍历中,根节点的值在序列的中间,左子树的节点再根节点的左边右子树的节点在树的右边。
1.根据前序和中序的特点得到根节点为1的左右子树图:
2.根节点1的左指针指向2的左右子树图:
3.等等都是用同样的方法来构建左右子树,也就是说,我们可以用递归的方法来实现。
代码:
#pragma once
struct BinaryTreeNode
{
int _data;
BinaryTreeNode* _left;
BinaryTreeNode* _right;
BinaryTreeNode(const int& data)
:_data(data)
,_left(0)
,_right(0)
{}
};
typedef BinaryTreeNode Node;
//递归的思想
Node* construct(int* startpreorder,int* endpreorder,int* startinorder,int* endinorder)
{
int rootvalue=startpreorder[0]; //根节点的值
Node* root=new Node(rootvalue);
if(startpreorder==endpreorder) //只有一个节点
{
if(startinorder==endinorder&&*startpreorder==*startinorder)
return root;
else
{
return NULL;
}
}
int* inorderroot=startinorder; //在中序中找到根节点的值
while(inorderroot<=endinorder)
{
if(*inorderroot==rootvalue)
break;
inorderroot++;
}
if(inorderroot==endinorder&&*inorderroot!=rootvalue)
return NULL;
int LeftLenght=inorderroot-startinorder; //左树的长度
int* LeftPreorderEnd=startpreorder+LeftLenght; //在前序中左子树最后的一个节点
if(LeftLenght>0)
{
//构建左子树
root->_left =construct(startpreorder+1,LeftPreorderEnd,
startinorder,inorderroot-1);
}
if(LeftLenght<endpreorder-startpreorder)
{
//构建右子树
root->_right =construct(LeftPreorderEnd+1,
endpreorder,inorderroot+1,endinorder);
}
return root;
}
Node* Construct(int* preorder,int* inorder,int length)
{
if(preorder==NULL||inorder==NULL||length<=0)
return NULL;
return construct(preorder,preorder+length-1,inorder,inorder+length-1);
}
void PreOrder(Node* root)
{
if(root==NULL)
return;
cout<<root->_data <<" ";
PreOrder(root->_left );
PreOrder(root->_right );
}
void InOrder(Node* root)
{
if(root==NULL)
return;
InOrder(root->_left );
cout<<root->_data <<" ";
InOrder(root->_right );
}
void TestBinaryTree()
{
/*int preorder[]={1,2,4,7,3,5,6,8};
int inorder[]={4,7,2,1,5,3,8,6};*/
int preorder[]={3,5,6,8};
int inorder[]={5,3,8,6};
Node* root=Construct(preorder,inorder,8);
PreOrder(root);
cout<<endl;
InOrder(root);
cout<<endl;
}