由中序序列和后序序列确定先序序列【洛谷p1030】

题目来源:洛谷p1030

题目内容

给出一棵二叉树的中序与后序排列。求出它的先序排列。(约定树结点用不同的大写字母表示,长度≤8)。

输入输出

输入:2行,均为大写字母组成的字符串,表示一棵二叉树的中序与后序排列。

BADC
BDCA

输出:1行,表示一棵二叉树的先序。

ABCD

其他样例:

输入:
CBAFEGD
CFGEADB
输出:
BCDAEFG

输入:
DCBA
DCBA
输出:
ABCD
Code
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

string s1,s2,s3="";

/*
    找到中序序列中的根
    参数:当前数在中序序列的范围[midl,midr] 后序序列的范围[backl,backr] 字符串s
    根据后序序列末尾确定根,在中序序列中查找该根的位置,确定左右子树的个数
*/
void searchtree(int midl, int midr, int backl, int backr, string &s3){
    if(midl > midr || backl > backr) return;
    s3 += s2[backr]; //后序序列的末尾为根结点
    int p = midl;
    while(s1[p] != s2[backr]) p++; //找到中序序列中根结点在的位置
    int cnt = p - midl; //左子树结点的个数 = 跟结点的位置-初始位置
    searchtree(midl, p-1, backl, backl + cnt -1, s3); //左子树,分别在两个序列中的对应范围
    searchtree(p+1, midr,  backl + cnt, backr-1, s3); //右子树,分别在两个序列中的对应范围
}

int main(){
    cin >> s1;
    cin >> s2;
    searchtree(0, s1.size()-1, 0, s1.size()-1, s3);
    cout << s3 << endl;
    return 0;
}


/*
    找到中序序列中的根
    参数:当前的根,中序序列,当前子树的范围[a,b],当前根的位置,后序序列,结果序列
    根据后序序列确定在中序序列中的子树的根在哪里
    该方法不严谨,只能通过80%样例,因为需要控制后序遍历中的范围。
*/

// int searchx(string s, char c){ //在字符串s中[a,b]的位置寻找字符c的位置
//     for(int i = 0; i <= s.size()-1; i++){
//         if(s[i] == c) return i;
//     }
//     return -1;
// }
// void searchtree(char root, int a, int b, int rootx, string &s3){
//     if(a > b || b >= s2.size() || a < 0 ) return; //如果区间已经左>右,说明区间内已经处理完毕,直接返回,否则会死循环
//     if(a == b){
//         s3 += s1[a];
//         return;
//     }
//     s3 += root; //先序序列先把根结点加进去
//     cout <<"111 " << s3 << endl;
//     if(a == rootx) return; //如果左边界就是当前根结点,则不需要再搜索左子树
//     else{
//         if(b != rootx){ 
//             char ch = s1[rootx+1]; //中序序列中右子树第一个点为分割后序序列中前后子树的部分
//             int rootxl = searchx(s2, ch)-1; //后序序列中左子树的根的位置 
//             char newrootl = s2[rootxl]; //在后序序列中找到左子树新的根的字符
//             int xl = searchx(s1, newrootl); //在中序序列中左子树的根的位置
//             searchtree(newrootl, a, rootx-1, xl, s3);
//         }
//         else{ //如果右边界是根结点,左子树的根为后序序列的当前根结点前一位
//             searchtree(s2[rootx-1], a, rootx-1, searchx(s1,s2[rootx-1]), s3);
//         }
//     }
//     if(b == rootx) return; 如果右边界就是当前根结点,则不需要再搜索右子树
//     else{
//         int rootxr = searchx(s2, root)-1;
//         char newrootr = s2[rootxr] ; //在后序序列中找到右子树新的根的字符
//         int xr = searchx(s1, newrootr);
//         searchtree(newrootr, rootx+1, b, xr, s3);
//     }
//     return;
// }
TIPS
  1. 充分利用序列条件,遵循从后序找根,从中序找范围的准则进行递归。
  2. 注意细节,找范围时个数,控制边界等。
  3. 注意边界。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值