7-6 还原二叉树 (25 分)

给定一颗满二叉树的中序遍历序列和前/后序遍历序列。请尝试还原该二叉树并给出其层次遍历序列。

输入格式:
输入仅有一组样例。

第一行给出该满二叉树的高度H(3≤H≤20)(只有根节点的树的高度记为1)。

随后2行中,其中一行给出中序遍历的序列,另外一行可能给出的是前序遍历的序列、也可能给出的是后序遍历的序列。序列元素保证在整型范围内且互不相同。

注:输入的2组序列,中序遍历序列可能是第1组,也可能是第2组。

输出格式:
输出该满二叉树的层次遍历序列。

输入样例1:
3
1 2 4 5 3 6 7
4 2 5 1 6 3 7
输出样例1:
1 2 3 4 5 6 7
输入样例2:
3
4 2 5 1 6 3 7
4 5 2 6 7 3 1
输出样例2:
1 2 3 4 5 6 7

此题的难点在于未告知:给出的数组顺序(1.前序遍历,中序遍历)(2.中序遍历,前序遍历)(3.后序遍历,中序遍历)(4.中序遍历,后序遍历)这四种排列组合中的哪一种。
但是好在其是一个满二叉树,因此中序遍历数组的中间值为根节点,就此展开讨论进行假设,前序遍历数组第一个值也是根节点,后序遍历数组最后一个值也是根节点

#include <iostream>
#include <math.h>
#include<queue>
#define maxn 10000000
using namespace std;
int b1[maxn],b2[maxn];
int pre[maxn],in[maxn],post[maxn]; //存放先序,中序,后续的数组

struct node{     //定义结构体建立树节点
int data;
node* lchild;
node* rchild;
};

node* creaprein(int prel,int prer,int inl,int inr) //先序和中序建立树
{
    if(prel>prer) return NULL; //递归边界,长度小于等于0,直接返回
    node* root=new node;       //建立新节点,存放根节点
    root->data=pre[prel];      //根节点的数据域是根节点的值
    int i;                      
    for(i=inl;i<=inr;i++)
    {
         if(in[i]==pre[prel])  //找到该节点,并记录下标值
            break;
    }
    int num=i-inl; 
    root->lchild=creaprein(prel+1,prel+num,inl,i-1);  //递归其左子树
    root->rchild=creaprein(prel+num+1,prer,i+1,inr);  //递归其右子树
    return root;      //递归终点,返回根节点
}
node* creainpost(int postl,int postr,int inl,int inr) //中序和后序建立树
{  
    if(postl>postr) return NULL;    //递归边界
    node* root=new node;
    root->data=post[postr];   //先序和后序不同的就在于这里
    int i;
    for(i=inl;i<=inr;i++)
    {
        if(in[i]==post[postr])
            break;
    }
    int num=i-inl;
    root->lchild=creainpost(postl,postl+num-1,inl,i-1);//递归其左子树
    root->rchild=creainpost(postl+num,postr-1,i+1,inr);//递归其右子树
    return root;
}
void prin(node* root,int num)  //层序遍历输出
{
    queue<node*> q;   //建立队列,并且这是node型指针
    q.push(root);   //压入根节点
    while(!q.empty())  //判断队列是否为空,从而结束循环
    {
        node* now=new node;
        now=q.front();    //建立新节点并且取出队列首元素,取出不是删除,类似一个把队首元素赋值的意思
        cout<<now->data;   //输出队首元素的值
        num--;
        if(num != 0)
        cout<< " ";
        q.pop();    //输出完之后就可以pop掉队首元素
        if(now->lchild!=NULL)   //但是此时的now依旧存在 判断他是否有左孩子 
        q.push(now->lchild);   //递归左孩子
        if(now->rchild!=NULL)
        q.push(now->rchild);   //递归右孩子
    }
}


int main()
{
	int H;
	cin >> H ;
	int num = pow(2,H) - 1;
    int q = 0,h = 0;
	for(int i = 1;i <= num;i++)
	{
		cin >> b1[i];
    }
    for(int i = 1;i <= num;i++)
    {
    	cin >> b2[i];
	}
	if(b1[(num+1)/2] == b2[1])
	{
		for(int i = 1;i <= num;i++)
		{
			in[i] = b1[i];
			pre[i] = b2[i];
		}
		q++; 
	}
		if(b1[(num+1)/2] == b2[num])
	{
		for(int i = 1;i <= num;i++)
		{
			in[i] = b1[i];
			post[i] = b2[i];
		}
		h++;
	}    //假设数组b1为中序遍历 
		if(b2[(num+1)/2] == b1[1])
	{
		for(int i = 1;i <= num;i++)
		{
			in[i] = b2[i];
			pre[i] = b1[i];
		}
		q++;
	}
		if(b2[(num+1)/2] == b1[num])
	{
		for(int i = 1;i <= num;i++)
		{
			in[i] = b2[i];
			post[i] = b1[i];
		}
		h++;
	}

	
	if(q != 0)
	{
		node* root = creaprein(1,num,1,num);
		prin(root,num);
	}
	if(h != 0)
	{
        node* root=creainpost(1,num,1,num);  
        prin(root,num);   
	}

}
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值