求先序排列(NOIP2001&NOIP水题测试(2017082301))

题目链接:求先序排列
这道题讲白了,就是数的构造,然后遍历。
思路大致是这样:
我们先通过后序遍历,找到当前区间的根,然后在中序遍历中找到根对应的下标,然后就可以分出左右子树,建立当前根与左右子树根的关系,然后分为两段,重复该操作即可。
先序遍历也没有什么难的,先输出根,然后判断是否有左右子树,有的话递归输出,没有就算。
下面上代码:

#include<bits/stdc++.h>
using namespace std;
struct point{                           //1
    int p;                              //2
    int lc;
    int rc;
}poi[26];                              //3
void build(int* mid,int* back,int ml,int mr,int bl,int br){
    if(mr-ml<1){                       //4
        return;
    }
    int root=back[br];                 //5
    int index;
    for(int i=ml;i<=mr;i++){
        if(mid[i]==root){
            index=i;                    //6
            break;
        }
    }
    if(index-1>=ml){                 //7
        poi[root].lc=back[index-1-ml+bl];
        poi[back[index-1-ml+bl]].p=root;
        build(mid,back,ml,index-1,bl,index-1-ml+bl);
    }
    if(mr>=index+1){
        poi[root].rc=back[br-1];
        poi[back[br-1]].p=root;
        build(mid,back,index+1,mr,index-ml+bl,br-1);
    }


}
void treeprint(int root){
    printf("%c",root+'A');               //8
    if(poi[root].lc!=-1){                //9
        treeprint(poi[root].lc);   
    }
    if(poi[root].rc!=-1){
        treeprint(poi[root].rc);
    }
}
int main(){
    char mid[10],back[10];
    int midn[10],backn[10];                  
    char c;
    scanf("%s",mid);
    scanf("%c",&c);
    scanf("%s",back);
    for(int i=0;i<26;i++){               //10
        poi[i].p=-1;
        poi[i].lc=-1;
        poi[i].rc=-1;
    }
    int i;
    for(i=0;mid[i]!='\0';i++){          //11
        midn[i]=mid[i]-'A';
    }
    for(i=0;back[i]!='\0';i++){
        backn[i]=back[i]-'A';
    }
    int root=backn[i-1];
    build(midn,backn,0,i-1,0,i-1);
    treeprint(root);
    return 0;
}

讲11点(怪多的哈):
1处:写一个节点结构体。
2处:这个记录父亲没什么用,放在这里仅仅是为了保持节点数据的完整性。
3处:题目没有明确说只用前八个字母,所以还是小心点好,防止被坑。
4处:如果区间长度小于等于1,也就不可能再有子树,那么返回。
5处:找到根。
6处:找到根在中序遍历中的坐标。
7处:判断中序遍历中,根的左右边是否有字符,如果有说明有子树。
8处:打印当前根。
9处:判断是否有子节点。
10处:结构体数据初始化,用于判断左右子树是否为空。
11处:转化成数字便于处理,输出时别忘了转化回去。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值