pascal给出一棵二叉树的中序与后序排列。求出它的先序排列(帮忙解释一下程序)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了pascal给出一棵二叉树的中序与后序排列。求出它的先序排列(帮忙解释一下程序)相关的知识,希望对你有一定的参考价值。

var
s1,s2:string;
procedure solve(s1,s2:string);
var
k:integer;
begin
if length(s2)=1 then write(s2)
else begin
k:=pos(s2[length(s2)],s1);
write(s1[k]);
if k>1 then solve(copy(s1,1,k-1),copy(s2,1,k-1));
if k<length(s1)
then
solve(copy(s1,k+1,length(s1)-k),copy(s2,k,length(s2)-k));
end;
end;
begin
assign(input,'xianxu.in');reset(input);
assign(output,'xianxu.out');rewrite(output);
readln(s1);
readln(s2);
solve(s1,s2);
close(input);
close(output);
end.
额....虽然你说的很详细(首先,先谢谢你啦)但是,我还是想不怕死的问一句:solve(copy(s1,1,k-1),copy(s2,1,k-1))
solve(copy(s1,k+1,length(s1)-k),copy(s2,k,length(s2)-k));是怎么来的,谢谢啦~~~我没多少分,全给你好了....别嫌弃的说...~~~

首先知道:
先序:根左右;后序,左右根;中序,左根右。
看过程:是递归调用的:
if length(s2)=1 then write(s2){如果当前后序遍历只有一个就直接输出该位置}
else begin
k:=pos(s2[length(s2)],s1);{后序排序的最后一个是当前序列的根,寻找根在中序排序中的位置,则中序排序被跟分成前面后面两节,前面那节是左子树,后面是右子树}
write(s1[k]);{先序是先输出根}
if k>1 then solve(copy(s1,1,k-1),copy(s2,1,k-1));{如果左子树存在就递归调用}
if k<length(s1)
then
solve(copy(s1,k+1,length(s1)-k),copy(s2,k,length(s2)-k));{如果存在右子树递归调用}
end;

solve(copy(s1,1,k-1),copy(s2,1,k-1))本句话的意思是,s1序列从第1个到第k-1个是左子树,s2前面同样的长度也是左子树,所以,相当于把这个问题又分成了个新的和先一样的问题,已知中序和后序,求先序,那不就是可以递归了,只不过长度改变了,变成原来的左子树。
其实意思很简单,就是每次都找到根输出,然后遍历左子树,遍历右子树,然后对左子树同样,先输出根,再访问左子树,右子树,。。。递归调用。
那么每次就是要找到根是哪个就可以,所以我门根据: 先序:根左右;后序,左右根;中序,左根右。特点知道怎么找根,然后递归调用。
同理可以知道
solve(copy(s1,k+1,length(s1)-k),copy(s2,k,length(s2)-k));
是在访问递归调用右子树。
参考技术A 例2求先序排列 (NOIP2001pj)
[问题描述]给出一棵二叉树的中序与后序排列。求出它的先序排列。(约定树结点用不同的大写字母表示,长度≤8)。
[样例] 输入:BADC BDCA 输出:ABCD
算法分析:我们先看看三种遍历的定义:
先序遍历是先访问根结点,再遍历左子树,最后遍历右子树;
中序遍历是先遍历左子树,再访问根结点,最后遍历右子树;
后序遍历是先遍历左子树,再遍历右子树,最后访问根结点;
从遍历的定义可知,后序排列的最后一个字符即为这棵树的根节点;在中序排列中,根结点前面的为其左子树,根结点后面的为其右子树;我们可以由后序排列求得根结点,再由根结点在中序排列的位置确定左子树和右子树,把左子树和右子树各看作一个单独的树。这样,就把一棵树分解为具有相同性质的二棵子树,一直递归下去,当分解的子树为空时,递归结束,在递归过程中,按先序遍历的规则输出求得的各个根结点,输出的结果即为原问题的解。
源程序
program noip2001_3;
var z,h : string;
procedure make(z,h:string); z为中序排列,h为后序排列
var s,m : integer;
begin
m:=length(h);m为树的长度
 write(h[m]); 输出根节点
 s:=pos(h[m],z); 求根节点在中序排列中的位置
 if s>1 then make(copy(z,1,s-1),copy(h,1,s-1)); 处理左子树
 if m>s then make(copy(z,s+1,m-s),copy(h,s,m-s)); 处理右子树
end;
begin
 readln(z);
 readln(h);
 make(z,h);
end.

P1030求先序排列

这道题很重点啊。。。
首先是对树的理解,了解先序、中序、后序的排列
再自己找出排列的规律。
初学树状结构做这道题能加深自己的理解。
以及判定范围。。。40分惨痛教训。。。

 传送门

题目描述

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

输入输出格式

输入格式:

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

输出格式:

111行,表示一棵二叉树的先序。

输入输出样例

输入样例#1: 复制
BADC
BDCA
输出样例#1: 复制
ABCD
上代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<map>
#include<queue>
#include<cstring>
#include<algorithm>
using namespace std;
template <typename T>inline void read(T &a)
{
    bool f=0;char ch=getchar();a=0;
    while(ch<0||ch>9){if(ch==-)f=1;ch=getchar();}
    while(ch>=0&&ch<=9){a=a*10+ch-0;ch=getchar();}
    if(f==1)a=-a;
}//好习惯,虽然没用上。
char l[9],m[9];
int s;
void find(int ll,int lr,int ml,int mr)
{
    cout<<l[lr];
    if(ll==lr)
    return;
    int root;
    for(int i=ml;i<=mr;i++)
    if(m[i]==l[lr])
    {
        root=i;
        break;
    }
    if(root>ml)//判范围!!!判范围!!
    find(ll,ll+root-ml-1,ml,root-1);
    if(root<mr)//判范围!!!判范围!!
    find(ll+root-ml,lr-1,root+1,mr);
    
}
int main(){
scanf("%s",m);
scanf("%s",l);
s=strlen(l);
find(0,s-1,0,s-1);
return 0;
}

 


以上是关于pascal给出一棵二叉树的中序与后序排列。求出它的先序排列(帮忙解释一下程序)的主要内容,如果未能解决你的问题,请参考以下文章

求先序排列

P1030 求先序排列

luogu1030 求先序排列

P1030求先序排列

洛谷 P1030 求先序排列 Label:None

codevs 1013 求先序排列(二叉树遍历)