真值二叉树重构

清华OJ

#include <stdio.h>
#include <stdlib.h>
#define maxSize 4000001
int NumOfNode;//结点个数
int last;

const int SZ = 1 << 20;  //提升IO buff
struct fastio
{
    char inbuf[SZ];
    char outbuf[SZ];
    fastio()
    {
        setvbuf(stdin, inbuf, _IOFBF, SZ);
        setvbuf(stdout, outbuf, _IOFBF, SZ);
    }
} io;


struct TreeNode
{
	TreeNode *leftchild, *rightchild;
	int elem;
	TreeNode():leftchild(NULL),rightchild(NULL){}
}TreeNodes[maxSize];

int PreOrder[maxSize], PostOrder[maxSize];

template <class T>//输入加速
inline void scan_d(T &ret) {
	char c; ret=0;
	while((c=getchar())<'0'||c>'9');
	while(c>='0'&&c<='9') ret=ret*10+(c-'0'),c=getchar();
}


int FindLeftRoot(int prefirst, int preend, int postfirst, int postend)// 寻找左子树树根结点在后序序列的位置
{
    for (int i = postfirst; i <= postend; i++)
	{
		if (PostOrder[i] == PreOrder[prefirst + 1]) // PreOrder[prefirst+1]:左子树树根
		{
			return i;
		}
	}
	return -1;
}

TreeNode *BuildTree(int prefirst, int preend, int postfirst, int postend)
{  // 前序序列[prefirst,preend],后序序列[postfirst,postend]
	TreeNode *root = new TreeNode();
	root->elem = PreOrder[prefirst];
	if (postfirst == postend) return root;
	int LeftRootId=FindLeftRoot(prefirst,preend,postfirst,postend);
	root->leftchild = BuildTree(prefirst + 1, LeftRootId - postfirst + prefirst + 1, postfirst, LeftRootId);
	root->rightchild = BuildTree(LeftRootId - postfirst + prefirst + 2, preend, LeftRootId + 1, postend - 1);
	return root;
}

void outputByInOrder(TreeNode *tree)//中序输出
{
    if (tree->leftchild != NULL) outputByInOrder(tree->leftchild);
	printf("%d ", tree->elem);
	if (tree->rightchild != NULL) outputByInOrder(tree->rightchild);
}

int main()
{
	//输入
	last = 0;
    scan_d(NumOfNode);
	for (int i = 0; i < NumOfNode; i++)
		scan_d(PreOrder[i]);
	for (int i = 0; i < NumOfNode; i++)
        scan_d(PostOrder[i]);
	//
	TreeNode *tree = BuildTree(0, NumOfNode - 1, 0, NumOfNode - 1);
	outputByInOrder(tree);
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值