《剑指offer》:[10]利用前序和中序构建二叉树

        树是一种在实际编程中经常遇到的数据结构。它的逻辑比较简单,除了根节点之外每个节点只有一个父节点,根节点没有父节点。除了叶子结点外所有的结点都有一个或者多个子节点,子节点没有叶子节点。父节点与子节点之间用指针来连接。
       但是我们经常用到的数据结构为:二叉树。所谓二叉树是树的一种特殊结构,在二叉树中,每个结点最多只能有两个结点。下面我们来看一下树的一些相关概念:参考书籍为:《数据结构与算法(C++版)》第六章:树与二叉树

图能表达的更直观,所以下面用一张图来表示其中的概念。虽然比较简单,复习一下。


 下面步入正题:重建二叉树,已知前序遍历和中序遍历重建一棵二叉树。注意只有前序和后序是不能确定二叉树的,必须要有中序遍历。
前序序列:{1,2,4,7,3,5,6,8};
中序序列:{4,7,2,1,5,3,8,6};

通过前序中序,中序和后序是可以确定二叉树的,这里不再多赘述,应该很简单!
实现代码如下:
#include <iostream>
using namespace std;
struct BinaryTree
{
	int data;
	BinaryTree *pLeft;
	BinaryTree *pRight;
};

BinaryTree* Construct(int *preorder,int *inorder,int length);
BinaryTree *ConstructCore(int *startpreorder,int *endpreorder,int *startinorder,int *endinorder);

int Preorder[8]={1,2,4,7,3,5,6,8};
int Inorder[8]={4,7,2,1,5,3,8,6};
BinaryTree* Construct(int *preorder,int *inorder,int length)
{
	if(NULL==preorder || NULL==inorder || length <=0)
		return NULL;
	return ConstructCore(preorder,preorder+length-1,inorder,inorder+length-1);
}

BinaryTree *ConstructCore(int *startpreorder,int *endpreorder,int *startinorder,int *endinorder)
{
	int rootvalue=startpreorder[0];
	BinaryTree *root=new BinaryTree;
	root->data=rootvalue;
	root->pLeft=root->pRight=NULL;
	if(startpreorder==endpreorder)
	{
		if(startinorder==endinorder && *startinorder==*endinorder)
			return root;
		else
			throw exception("1.INVALID INPUT!");
	}
	int *rootinorder=startinorder;
	int leftlength=0;
	while(rootinorder<=endinorder && *rootinorder!=rootvalue)
	{
		++rootinorder;
		++leftlength;
	}
	if(rootinorder==endinorder && *rootinorder!=rootvalue)
		throw exception("2.INVALID input!");
	int *leftpreorderend=startpreorder+leftlength;
	if(leftlength>0)
	{
		root->pLeft=ConstructCore(startpreorder+1,leftpreorderend,startinorder,rootinorder-1);
	}
	if(leftlength < endpreorder-startpreorder)
	{
		root->pRight=ConstructCore(leftpreorderend+1,endpreorder,rootinorder+1,endinorder);
	}
	return root;
}
void PreOrder(BinaryTree *root) //前序遍历;
{
	BinaryTree *temp=root;
	if(temp)
	{
		cout<<temp->data<<" ";
		PreOrder(temp->pLeft);
		PreOrder(temp->pRight);
	}
}

void PostOrder(BinaryTree *root)
{
	BinaryTree *temp=root;
	if(temp)
	{
		PostOrder(temp->pLeft);
		PostOrder(temp->pRight);
		cout<<temp->data<<" ";
	}
}
void Destory(BinaryTree *root)
{
	if(root)  
	{
		Destory(root->pLeft);
		delete(root->pLeft);
		Destory(root->pRight);
		delete(root->pRight);
	}
}
int main()
{
	BinaryTree *root=NULL;
	try
	{
		root=Construct(Preorder,Inorder,8);
	}
	catch (char* str)
	{
		cout<<"exception:"<<str<<endl;
	}
	
	cout<<"PreOrder:"<<endl;
	PreOrder(root);
	cout<<endl;

	cout<<"PostOrder:"<<endl;
	PostOrder(root);
	cout<<endl;

	Destory(root);
	system("pause");
	return 0;
}

树的形状:


运行结果:


有修改,在此感谢 lhhero701 指出文中的一个错误!





评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值