重建二叉树

16 篇文章 0 订阅

     对二叉树有点了解的都知道,通过中序和任何遍历都可以唯一构建好一个二叉树,所以我们可以以中序和前序为例,来重建一棵二叉树:

#include <iostream>
using namespace std;
struct tree_node  //树节点的结构体
{
	int m_data;
	tree_node *m_cright;
	tree_node *m_cleft;
};

class solution
{
public:
	tree_node* Recreate(int *preorder,int *inorder,int length) //形参分别表示前序遍历,中序遍历和长度
	{
		if(preorder==NULL||inorder==NULL||length<=0)
			return NULL;
		return _create(preorder,preorder+length-1,inorder,inorder+length-1);
	}

	//递归后序遍历
	void backorder(tree_node *root)
	{
		if(root==NULL)
			return;
		backorder(root->m_cleft);
		backorder(root->m_cright);
		cout<<root->m_data<<" ";
	}
private:
	tree_node* _create(int *start_pre,int *end_pre,int *start_in,int *end_in)
	{
		//根据前序遍历的第一个数据是根节点
		int root_data=start_pre[0];//取出当前的根节点
		tree_node* root=new tree_node; //在堆中开辟保存根节点的内存
		root->m_cleft=NULL;
		root->m_cright=NULL;
		root->m_data=start_pre[0];
		if(start_pre==end_pre)//当前只有一个结点,没有左右子树了
		{
			if(start_in==end_in&&*start_pre==*start_in)//中序遍历数组也只有一个元素,且和前序遍历的数据相等,则输入正确
			{
				return root;
			}
			else
				throw std::exception("无效的输入");
		}

		//在中序遍历中找到根节点的位置
		int* root_position=start_in;
		while(root_position<=end_in&&*root_position!=root_data)
			++root_position;
		if(root_position==end_in&&*root_position!=root_data)//到达末尾还不相等,则匹配错误
			throw std::exception("匹配错误"); //匹配错误

		int left_num=root_position-start_in ;//左子树的个数
		if(left_num>0)
		{
			root->m_cleft=_create(start_pre+1,start_pre+left_num,start_in,root_position-1);
		}
		if(left_num<end_in-start_in) //还有右子数
		{
			root->m_cright=_create(start_pre+left_num+1,end_pre,root_position+1,end_in);
		}
		return root;
	}
};


int main()
{
	solution s;
	int preorder[8]={1,2,4,7,3,5,6,8};
	int inorder[8]={4,7,2,1,5,3,8,6};
	tree_node *root=s.Recreate(preorder,inorder,8);
	s.backorder(root);
}

思路:通过前序遍历的第一个元素可以得到该二叉树的根节点,,然后在中序遍历的数组中找到根节点(由前序遍历得到),中序遍历的数组中根节点的左边是左子树,右边是右字数,然后由左右子树的个数在前序遍历中分别找到左右子树的前序遍历,然后由左右子树的前序和中序遍历得到子树的根节点,一次类推。。。用递归的方式就可以重建好二叉树。

总结:

    中序+前序、后序、层次遍历可以唯一地确定一个二叉树;

     前序、后序、层次遍历中的任意两个遍历都不能唯一地确定一个二叉树。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值