树的重建

树的重建

本文收集该写了树的重建各种情景方法:
1. 已知前序遍历和中序遍历,求后序遍历
2. 已知后序遍历和中序遍历,求前序遍历
3. 已知前||中||后序遍历(保证为完全二叉树),求层序遍历
4. 已知层序遍历(保证为完全二叉树),求前、中、后序遍历

注:理解1和2时要紧扣前序、后序遍历和中序遍历的区别。
理解3和4时要紧扣完全二叉树的数组存储规律。

测试样例:
结点个数:8
前序遍历:18 34 71 91 2 55 10 15
中序遍历:91 71 34 2 18 10 55 15
后序遍历:91 71 2 34 10 15 55 18
层序遍历:18 34 55 71 2 10 15 91

1、已知前序遍历和中序遍历,求后续遍历。

#include<stdio.h>

const int N=10000;
int n,pos;    //n存树的结点个数
int pre[N],in[N],post[N],idx;    //pre存前序遍历,in存中序遍历,post存后序遍历

int f(int x)    //返回in中等于x的下标
{
    for(int i=0;i<n;i++)
        if(in[i]==x)
            return i;
}

void rec(int l,int r)    
{
    if(l>=r)   return ;
    int root=pre[pos++];
    int m=f(root);
    rec(l,m);
    rec(m+1,r);
    post[idx++]=root;
}

void solve()
{
    pos=0;
    rec(0,n);
    for(int i=0;i<n;i++)
        printf("%d ",post[i]);
}

int main()
{
    int k;
    scanf("%d",&n);
    for(int i=0;i<n;i++)
        scanf("%d",&pre[i]);
    for(int i=0;i<n;i++)
        scanf("%d",&in[i]);
    solve();
    return 0;
}

2、已知后序遍历和中序遍历,求前序遍历

#include<stdio.h>

const int N=10000;
int n,pos;    //n存树的结点个数
int pre[N],in[N],post[N],idx;    //pre存后序遍历,in存中序遍历,post存前序遍历

int f(int x)    //返回in中等于x的下标
{
    for(int i=0;i<n;i++)
        if(in[i]==x)
            return i;
}

void rec(int l,int r)    
{
    if(l>=r)   return ;
    int root=pre[pos--];
    int m=f(root);
    rec(m+1,r);
    rec(l,m);
    post[idx++]=root;
    
}

void solve()
{
    pos=n-1;
    rec(0,n);
    for(int i=n-1;i>=0;i--)
        printf("%d ",post[i]);
}

int main()
{
    int k;
    scanf("%d",&n);
    for(int i=0;i<n;i++)
        scanf("%d",&pre[i]);
    for(int i=0;i<n;i++)
        scanf("%d",&in[i]);
    solve();
    return 0;
}

3、已知前序遍历和后序遍历不可求中序遍历

4、已知前序||中序||后序遍历(保证该树为完全二叉树),求层序遍历

#include<bits/stdc++.h>
using namespace std;
int n,a[100],tree[100];
int idx=1;
void f(int x)
{    
    if(x > n) return ;
    tree[x] = a[idx++];        //已知前序遍历,求层序遍历
    f(x << 1);
    //tree[x] = a[idx++];   //已知中序遍历,求层序遍历
    f((x << 1) + 1);
    //tree[x] = a[idx++];     //已知后序遍历,求层序遍历
}


int main(){
    scanf("%d",&n);
    for(int i = 1; i <= n; i++)
        scanf("%d",&a[i]);
    f(1);
    printf("层次遍历:");
    for(int i = 1; i <= n; i++)
        printf("%d ",tree[i]);
    return 0;
}

5、已知层序遍历,求前中后遍历

#include<stdio.h>
const int N=100;
int pre[N],in[N],post[N],tree[N],idx;;
int n;


void f(int x)
{
    pre[idx++]=tree[x];        //求前序遍历
    if(x<<1<=n)
        f(x<<1);
    //in[idx++]=tree[x];    //求中序遍历
    if((x<<1)+1<=n)         //记得加括号,不然会先加1后乘2
        f((x<<1)+1);
    //post[idx++]=tree[x];    //求后序遍历
}

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)    //输入层遍历
        scanf("%d",&tree[i]);


    f(1);     


    for(int i=0;i<n;i++)    //输出
        printf("%d ",pre[i]);
    return 0;
}

参考资料:
* 挑战程序设计竞赛2:算法和数据结构
* CNDN博客—— 小星星+yg https://blog.csdn.net/qq_42967669

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值