二叉树经典面试题5~由前序遍历和中序遍历还原二叉树

   由前序遍历和中序遍历的遍历序列还原一颗二叉树

   相信学过数据结构的童鞋都知道二叉树的常见遍历方式有四种:前序遍历,中序遍历,后序遍历,层序遍历;而前序遍历是广度优先遍历,层序遍历是广度遍历,在这里我就不多加叙述了,直奔主题吧!

   而这道面试题中考察的是利用前序和中序遍历构建二叉树,详细的分析见下图:

  

    通过上图的分析,我们知道要还原一棵二叉树首先要能够知道该二叉树的根结点,根据前序遍历序列的遍历方式:前-中-后,我们知道前序遍历的第一个结点是该二叉树的根结点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;
}

 总结:

     在这道面试题中考察的是二叉树的遍历方式的灵活运用,同时也考察了二叉树的不同的构建方式,通常创建二叉树的方式是用一个序列结合非法值并结合前序遍历的方式构建,在这里是利用前序+中序的方式还原二叉树,当然也可以通过中序+后序(后序遍历的最后一个结点是根结点)的方式还原

    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值