通过中序遍历和先序遍历结果构造二叉树

1. 给出中序遍历和先序遍历结果,构造二叉树


// ConstructTree.cpp : 定义控制台应用程序的入口点。
//

#include "stdio.h"
#include "stdlib.h"
#include "iostream"
#include "vector"
#include "stack"

using namespace std;

typedef struct Node
{
	int data;
	struct Node * lc;
	struct Node * rc;
}TreeNode, *TNode;


void Construct(int * inorderStart, int * inorderEnd, int * &preIndex, Node * &root);
void InOrder(Node * root);


int main(int argc, char * argv[])
{
	int preOrder[] = {1, 2, 4, 7, 3, 5, 6, 8};
	int inOrder[] =  {4, 7, 2, 1, 5, 3, 8, 6};

	Node * tree;

	int * inorderStart = inOrder;
	int * inorderEnd = inOrder + 7;
	int * preorder = preOrder;

	Construct(inorderStart, inorderEnd, preorder, tree);
	cout<<endl;
	InOrder(tree);

	system("pause");
	return 0;
}

// 通过中序遍历序列和先序遍历序列,构造二叉树,
// 还可以在构造的构成中输出后续遍历结果
// 地柜的调用
void Construct(int * inorderStart, int * inorderEnd, int * &preIndex, Node * &root)
{
	// 没有左子树
	if(inorderEnd < inorderStart)
		return;
	// 没有右子树
	if(inorderStart > inorderEnd)
		return;

	root = new Node;
	int data = *preIndex;
	root->data = data;
	root->lc = NULL;
	root->rc = NULL;

	if(inorderStart == inorderEnd)
	{
		// 遍历到叶子节点,相当于左右子树都为空  
		printf("%3d", root->data);
        return;
	}

	// 找到先序遍历的点在中序序列中的位置
	// 通过该位置递归的构造左子树和右子树
	int * pc = inorderStart;
	while(*pc != data)
	{
		pc++;
	}
	
	if(pc > inorderStart)
	{
		preIndex++;
		Construct(inorderStart, pc - 1, preIndex, root->lc);
	}

	if(pc < inorderEnd)
	{
		preIndex++;
		Construct(pc + 1, inorderEnd, preIndex, root->rc);
	}

	// 输出后续遍历结果
	printf("%3d", root->data);
}

// 中序遍历
void InOrder(Node * root)
{
	if(root)
	{
		InOrder(root->lc);
		printf("%3d", root->data);
		InOrder(root->rc);
	}
}


2. 根据中序结果和后续结果构造二叉树


// ConstructTree.cpp : 定义控制台应用程序的入口点。
//

#include "stdio.h"
#include "stdlib.h"
#include "iostream"
#include "vector"
#include "stack"

using namespace std;

typedef struct Node
{
	int data;
	struct Node * lc;
	struct Node * rc;
}TreeNode, *TNode;


void Construct(int * inorderStart, int * inorderEnd, int * &preIndex, Node * &root);
void Construct2(int * inorderStart, int * inorderEnd, int * &preIndex, Node * &root);
void InOrder(Node * root);


int main(int argc, char * argv[])
{
	int preOrder[]  = {1, 2, 4, 7, 3, 5, 6, 8};
	int inOrder[]   = {4, 7, 2, 1, 5, 3, 8, 6};
	int postOrder[] = {7, 4, 2, 5, 8, 6, 3, 1};

	Node * tree;

	int * inorderStart = inOrder;
	int * inorderEnd = inOrder + 7;
	int * preorder = preOrder;

	cout<<"构造二叉树,后续遍历"<<endl;
	Construct(inorderStart, inorderEnd, preorder, tree);
	cout<<endl;
	cout<<"中序遍历"<<endl;
	InOrder(tree);
	cout<<endl;

	int * postorder = postOrder + 7;
	cout<<"构造二叉树,递归书序,根据中序遍历和后续遍历结果构造二叉树"<<endl;
	Construct2(inorderStart, inorderEnd, postorder, tree);
	cout<<endl;
	cout<<"中序遍历"<<endl;
	InOrder(tree);

	system("pause");
	return 0;
}

// 通过中序遍历序列和先序遍历序列,构造二叉树,
// 还可以在构造的构成中输出后续遍历结果
// 地柜的调用
void Construct(int * inorderStart, int * inorderEnd, int * &preIndex, Node * &root)
{
	// 没有左子树
	if(inorderEnd < inorderStart)
		return;
	// 没有右子树
	if(inorderStart > inorderEnd)
		return;

	root = new Node;
	int data = *preIndex;
	root->data = data;
	root->lc = NULL;
	root->rc = NULL;

	if(inorderStart == inorderEnd)
	{
		// 遍历到叶子节点,相当于左右子树都为空  
		printf("%3d", root->data);
        return;
	}

	// 找到先序遍历的点在中序序列中的位置
	// 通过该位置递归的构造左子树和右子树
	int * pc = inorderStart;
	while(*pc != data)
	{
		pc++;
	}
	
	if(pc > inorderStart)
	{
		preIndex++;
		Construct(inorderStart, pc - 1, preIndex, root->lc);
	}

	if(pc < inorderEnd)
	{
		preIndex++;
		Construct(pc + 1, inorderEnd, preIndex, root->rc);
	}

	// 输出后续遍历结果
	printf("%3d", root->data);
}

// 中序遍历
void InOrder(Node * root)
{
	if(root)
	{
		InOrder(root->lc);
		printf("%3d", root->data);
		InOrder(root->rc);
	}
}

// 通过给定的后续遍历,中序遍历结果,构造二叉树
void Construct2(int * inorderStart, int * inorderEnd, int * &preIndex, Node * &root)
{
	// 没有左子树
	if(inorderEnd < inorderStart)
		return;
	// 没有右子树
	if(inorderStart > inorderEnd)
		return;

	root = new Node;
	int data = *preIndex;
	root->data = data;
	root->lc = NULL;
	root->rc = NULL;

	if(inorderStart == inorderEnd)
	{
		// 遍历到叶子节点,相当于左右子树都为空  
		printf("%3d", root->data);
        return;
	}

	// 找到先序遍历的点在中序序列中的位置
	// 通过该位置递归的构造左子树和右子树
	int * pc = inorderStart;
	while(*pc != data)
	{
		pc++;
	}

	// 递归右子树
	if(pc < inorderEnd)
	{
		preIndex--;
		Construct2(pc + 1, inorderEnd, preIndex, root->rc);
	}

	// 递归左子树
	if(pc > inorderStart)
	{
		preIndex--;
		Construct2(inorderStart, pc - 1, preIndex, root->lc);
	}

	// 输出后续遍历结果
	printf("%3d", root->data);
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值