2023.1.3(总结)

一,美国血统

题目描述

农夫约翰非常认真地对待他的奶牛们的血统。然而他不是一个真正优秀的记帐员。他把他的奶牛 们的家谱作成二叉树,并且把二叉树以更线性的“树的中序遍历”和“树的前序遍历”的符号加以记录而 不是用图形的方法。

你的任务是在被给予奶牛家谱的“树中序遍历”和“树前序遍历”的符号后,创建奶牛家谱的“树的 后序遍历”的符号。每一头奶牛的姓名被译为一个唯一的字母。(你可能已经知道你可以在知道树的两 种遍历以后可以经常地重建这棵树。)显然,这里的树不会有多于 26 个的顶点。 这是在样例输入和 样例输出中的树的图形表达方式:

         C
         /  \
        /  \
       B    G
      / \  /
       A   D  H
        / \
       E   F

树的中序遍历是按照左子树,根,右子树的顺序访问节点。

树的前序遍历是按照根,左子树,右子树的顺序访问节点。

树的后序遍历是按照左子树,右子树,根的顺序访问节点。

输入格式

第一行: 树的中序遍历

第二行: 同样的树的前序遍历

输出格式

单独的一行表示该树的后序遍历。

输入输出样例

输入 #1复制

ABEDFCHG
CBADEFGH 

输出 #1复制

AEFDBHGC

分析:

1,这个题目其实和昨天的那个求前序排列差不多,思路是差不多的。

2,此题给出了中序和前序,求后序,前序是根左右,中序是左根右,后序是左右根。

3,我们根据前序找到根,然后根据找到的根,在中序中找到根所在的位置,然后将中序以根为界限分为两部分,再根据中序分为的两部分,将前序也分为两部分,这两部分就是左子树和右子树。

4,我们先遍历左子树找根,再遍历右子树找根,重复上面的步骤,为什么是先左后右呢?因为后序的顺序是左右根,我们每一次找到的根都是放在最后,等左右子树找完之后才输出根,所以每次找到的根都放在它找完左右子树后输出。

5,需要注意的是,当我要找的子树已经找完了的时候就返回,结束此次递归,如果一直找,就会陷入死循环。

代码如下:

c++

#include<string>
#include<cstring>
#include<iostream>
#include<cstdio>
using namespace std;
string pre,inor;
void work(string pre,string inor)
{
    if(pre.empty())
    return;
    char root=pre[0];
    int k=inor.find(root);
    pre.erase(pre.begin());
    string leftpre=pre.substr(0,k);
    string rightpre=pre.substr(k);
    string leftinor=inor.substr(0,k);
    string rightinor=inor.substr(k+1);
    //cout<<"ff    "<<leftinor<<" "<<rightinor<<"   "<<leftpre<<" "<<rightpre<<endl;
    work(leftpre,leftinor);
    work(rightpre,rightinor);
    printf("%c\n",root);
}
int main()
{
    cin>>inor>>pre;
    work(pre,inor);
    return 0;
}

c语言

#include<stdio.h>
#include<string.h>
void tree(char z[26],char q[26])
{
    char c=q[0];
    char lz[26]={0},rz[26]={0},lq[26]={0},rq[26]={0};
    int k;
    if(strlen(q)==0)
    return;
    for(int i=0;i<strlen(z);i++)
    if(z[i]==c)
    {
        k=i;
        break;
    }
    for(int i=0;i<k;i++)
    lz[i]=z[i];
    int f=0;
    for(int i=k+1;i<strlen(z);i++)
    rz[f++]=z[i];
    for(int i=1;i<=k;i++)
    lq[i-1]=q[i];
    f=0;
    for(int i=k+1;i<strlen(q);i++)
    rq[f++]=q[i];
    //printf("ff   %s %s   %s %s\n",lz,rz,lq,rq);
    tree(lz,lq);
    tree(rz,rq);
    printf("%c",c);
}
int main()
{
    char z[26],q[26];
    scanf("%s%*c%s",z,q);
    tree(z,q);
}

二,新二叉树

## 题目描述

输入一串二叉树,输出其前序遍历。

## 输入格式

第一行为二叉树的节点数 $n$。($1 \leq n \leq 26$)

后面 $n$ 行,每一个字母为节点,后两个字母分别为其左右儿子。特别地,数据保证第一行读入的节点必为根节点。

空节点用 `*` 表示

## 输出格式

二叉树的前序遍历。

## 样例 #1

### 样例输入 #1

```
6
abc
bdi
cj*
d**
i**
j**
```

### 样例输出 #1
abdicj

分析:

1,前序是根左右,所以我们先找根,找到根之后就找左子树和右子树。

2,输入的数据,我们默认第一组数据的第一个字母就是根节点,所以第一个根节点我们直接输出就行,然后我们要找左子树和右子树的第一个值,也就是接下来的子树的根节点。

3,什么时候退出呢?那就是当子树已经完结也就是接下来没有子树的时候,就退出,就不用找了。

4,一定要注意内存的问题,我的内存就一直报错。

代码如下:

c++

#include<bits/stdc++.h>
using namespace std;
 
int n;
 
struct node{
    char lc,rc;
};
node tree[10001];
 
void dfs(char x)
{
    if(x=='*') return;
    cout<<x;
    dfs(tree[x].lc);
    dfs(tree[x].rc);
}
 
int main()
{
    cin>>n;
    char h1;
    cin>>h1;
    cin>>tree[h1].lc>>tree[h1].rc;
    for(int i=2;i<=n;i++){
        char h;
        cin>>h;
        cin>>tree[h].lc>>tree[h].rc;
    }
    dfs(h1);
}

c语言

#include<stdio.h>
#include<math.h>
#include<string.h>
char h,h1;
struct kk
{
    char l;
    char r;
}jd[200];


void ss(char head)
{
    if(head=='*')
    return;
    printf("%c",head);
    ss(jd[head].l);
    ss(jd[head].r);
}

int main()
{
    int n;
    scanf("%d",&n);
    for(int i=0;i<n;i++)
    {
        scanf(" %c",&h1);
        scanf("%c%c",&jd[h1].l,&jd[h1].r);
        if(i==0)
        h=h1;
    }
    ss(h);
}

总结:

1,今天重新复习了二叉树,二叉树的遍历的话,主要就是分为前序,中序,后序。

2,前序为根左右,中序为左根右,后序为左右根,一个巧记的点在于什么序那么根的位置就在什么地方。

3,一般的话,求序列使用的是递归,递归的特性很好求序列。

4,一般在求序列的时候是先找的根,再根据根找左右子树。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值