由前序遍历和中序遍历的遍历序列还原一颗二叉树
相信学过数据结构的童鞋都知道二叉树的常见遍历方式有四种:前序遍历,中序遍历,后序遍历,层序遍历;而前序遍历是广度优先遍历,层序遍历是广度遍历,在这里我就不多加叙述了,直奔主题吧!
而这道面试题中考察的是利用前序和中序遍历构建二叉树,详细的分析见下图:
通过上图的分析,我们知道要还原一棵二叉树首先要能够知道该二叉树的根结点,根据前序遍历序列的遍历方式:前-中-后,我们知道前序遍历的第一个结点是该二叉树的根结点0;其次要能够辨识出该二叉树的左子树结点和右子树结点,根据中序遍历可以知道结点0的左子树结点序列为3,1,4,右子树结点序列为5,2;然后通过递归解决。此时还原二叉树的思路已经解决了,那仫就来用代码实现吧。。。
实现代码如下:
template<class T>
struct BinaryTreeNode
{
T _data;
BinaryTreeNode<T> *_left;
BinaryTreeNode<T> *_right;
BinaryTreeNode(const T& data)
:_data(data)
,_left(NULL)
,_right(NULL)
{}
};
template<class T>
class BinaryTree
{
typedef BinaryTreeNode<T> Node;
public:
BinaryTree()
:_root(NULL)
{}
BinaryTree(T *pre,T *in,size_t size)
{
assert(pre && in);
//前序遍历的第一个结点就是根结点
_root=new Node(pre[0]);
_ReCreatTree(pre,in,size,_root);
}
void PostOrder()
{
_PostOrder(_root);
cout<<endl;
}
protected:
void _ReCreatTree(T *pre,T *in,size_t size,Node *&root)
{
if(size <= 0)
return ;
if(NULL == root)
root=new Node(pre[0]);
int index=0;
while (index < size)
{
if(in[index] == pre[0])
break;
++index;
}
int left=index;
int right=size-index-1;
_ReCreatTree(pre+1,in,left,root->_left);
_ReCreatTree(pre+index+1,in+index+1,right,root->_right);
}
void _PostOrder(Node *root)
{
if(NULL == root)
return ;
Node *cur=root;
if (cur)
{
_PostOrder(cur->_left);
_PostOrder(cur->_right);
cout<<cur->_data<<" ";
}
}
protected:
Node *_root;
};
void testCreatTreeByPreIn()
{
int pre[]={0,1,3,4,2,5};
int in[]={3,1,4,0,5,2};
size_t size1=sizeof(pre)/sizeof(pre[0]);
size_t size2=sizeof(in)/sizeof(in[0]);
if(size1 == size2)
{
BinaryTree<int> bt(pre,in,size1);
bt.PostOrder();
}
else
cout<<"error"<<endl;
}
总结:
在这道面试题中考察的是二叉树的遍历方式的灵活运用,同时也考察了二叉树的不同的构建方式,通常创建二叉树的方式是用一个序列结合非法值并结合前序遍历的方式构建,在这里是利用前序+中序的方式还原二叉树,当然也可以通过中序+后序(后序遍历的最后一个结点是根结点)的方式还原