树_还原二叉树

还原二叉树

若给出二叉树的前序和中序,或者给出二叉树的后序和中序,可以还原出唯一的二叉树。但给出前序和后序不可以。

1.前序和中序
递归算法

根据二叉树的前序序列和中序序列,还原二叉树。分析可知,前序序列的第一个元素是该二叉树的根结点,在中序序列中找到根结点的位置(下标),便可知道该二叉树的左右子树中各自结点的个数。据此,可将前序序列分为:根结点+左子树+右子树,将中序序列分为:左子树+根结点+右子树。问题又转化为,根据左右子树的前序序列和中序序列,分别还原二叉树(左右子树)。

  • 前序序列第一个元素:根结点
  • 利用根结点,划分前序序列和后序序列的左右子树
  • 递归调用,还原左右子树
  • 递归出口:左右子树为空树,即序列元素个数为0,左边界大于右边界
/*根据二叉树的前序和中序还原二叉树,递归算法,函数返回根结点*/
//设前序序列preorder[n+1],中序序列inorder[n+1],下标均为[1,n]
BiTNode *creat_Tree(int pre_L,int pre_R,int in_L,int in_R)
{
    //pre_L,pre_R分别为前序序列的左右边界下标,in_L,in_R同理为中序序列的边界下标
    if(pre_L>pre_R) return NULL;//递归出口,结点为空指针
    int pos;//记录根结点的下标
    for(int i=in_L;i<=in_R;i++)//在中序序列中找到根结点,记录下标
        if(inorder[i]==preorder[pre_L])//根结点为前序序列第一个元素
            {pos=i;break;}
    //建立根结点
    BiTNode *T=(BiTNode *)malloc(sizeof(BiTNode));
    T->data=preorder[pre_L];
    //还原左右子树
    T->lchild=creat_Tree(pre_L+1,pre_L+pos-in+L,in_L,pos-1);
    T->rchild=creat_Tree(pre_R-in_R+pos+1,pre_R,pos+1,in_R);
    //函数返回根结点
    return T;
}
2.后序和中序
递归算法

同理

  • 后序序列最后一个元素:根结点
  • 利用根结点,划分后序序列和后序序列的左右子树
  • 递归调用,还原左右子树
  • 递归出口:左右子树为空树,即序列元素个数为0,左边界大于右边界
/*根据二叉树的后序和中序还原二叉树,递归算法,函数返回根结点*/
//设后序序列postorder[n+1],中序序列inorder[n+1],下标均为[1,n]
BiTNode *creat_Tree(int post_L,int post_R,int in_L,int in_R)
{
    //post_L,post_R分别为后序序列的左右边界下标,in_L,in_R同理为中序序列的边界下标
    if(post_L>post_R) return NULL;//递归出口,结点为空指针
    int pos;//记录根结点的下标
    for(int i=in_L;i<=in_R;i++)//在中序序列中找到根结点,记录下标
        if(inorder[i]==postorder[post_R])//根结点为前序序列第一个元素
            {pos=i;break;}
    //建立根结点
    BiTNode *T=(BiTNode *)malloc(sizeof(BiTNode));
    T->data=postorder[post_R];
    //还原左右子树
    T->lchild=creat_Tree(post_L,post_L+k-in_L-1,in_L,k-1);
    T->rchild=creat_Tree(post_L+k-in_L,post_R-1,k+1,in_R);
    //函数返回根结点
    return T;
}
非递归算法
/*根据二叉树的后序和中序还原二叉树,非递归算法*/
#include<stdio.h>
//使用二叉树的顺序存储结构,二叉树所有结点存储在sqTree数组里
int sqTree[2001]={0}
int index_in[2001]={0};//存储对应结点i在中序序列inorder[]中的下标
int n;//结点总数

/*该函数将后序序列postorder[]中,从最后一个结点到第一个节点,一个个放入sqTree中*/
int put_root(int root,int inorder[],int postorder[]);

int main()
{
	scanf("%d", &n);
	int inorder[n+1],postorder[n+1];//中序序列和后序序列
	int lastnode=1;//二叉树在数组中最后一个结点的下标
	//初始化存储单元为0
	for(int i=0;i<1001;i++)
    {
        sqTree[i]=0;
        index_in[i]=0;
    }
    //输入后序序列,下标[1,n]
	for (int i = 1; i <=n; i++)
		scanf("%d", &postorder[i]);
    //输入中序序列,下标[1,n]
    for (int i = 1; i <=n; i++)
		scanf("%d", &inorder[i]);
	sqTree[1]=postorder[n];//根结点为后序序列最后一个元素
	for(int i=1;i<=n;i++)//找到根结点在中序序列中的下标,存入index_in[1]
        if(inorder[i]==sqTree[1])
        {
            index_in[1]=i;
            break;
        }
	//还原二叉树
	for(int i=n-1;i>=1;i--)
    {
        int k=put_root(postorder[i],inorder,postorder);
        if(k>lastnode) lastnode=k;//lastnode为数组中最后一个结点的下标,用于输出
    }
    //按照层序输出二叉树
    for(int i=0;i<lastnode;i++)
        if(sqTree[i]!=0)//0为不存在该结点
            printf("%d ",sqTree[i]);
    printf("%d",sqTree[result]);
	return 0;
}

/*该函数将后序序列postorder[]中,从最后一个结点到第一个节点,一个个放入sqTree中*/
int put_root(int root,int inorder[],int postorder[])
{
    //后序序列中,从后往前的元素必为某个子树的根结点,根据其在中序序列的位置
    int j,i=1;
    for(int k=1;k<=n;k++)
        if(inorder[k]==root)
        {
           j=k;break;
        }
    while(sqTree[i]!=0)
    {
        if(j>index_in[i])
            i=2*i+1;
        else if(j<index_in[i])
            i=2*i;
    }
    index_in[i]=j;sqTree[i]=inorder[j];
    return i;
}
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值