数据结构基础——二叉树

今天做题下来,体会最深的是结构体

首先我们需要会结构体

然后可以灵活运用深度优先dfs

下面是我会练习的一部分题,一些题我会放题解

接下来介绍一下二叉树

二叉树是每个结点最多有两个子树的树结构。

也就是说二叉树不允许存在度⼤于2的树。它有五种最基本的形态:二叉树可以是空集。根可以有空的左子树或者右子树;或者左右子树都是空。其中只有左子树或者右子树的叫做斜树


练习题

P4715 【深基16.例1】淘汰赛

题目描述

有 2^n(n≤7) 个国家参加世界杯决赛圈且进入淘汰赛环节。已经知道各个国家的能力值,且都不相等。能力值高的国家和能力值低的国家踢比赛时高者获胜。1 号国家和 2 号国家踢一场比赛,胜者晋级。3 号国家和 4 号国家也踢一场,胜者晋级……晋级后的国家用相同的方法继续完成赛程,直到决出冠军。给出各个国家的能力值,请问亚军是哪个国家?

输入格式

第一行一个整数 n,表示一共 2^n 个国家参赛。

第二行 2^n 个整数,第 i个整数表示编号为 i的国家的能力值(1≤i≤2^n)。

数据保证不存在平局。

输出格式

仅一个整数,表示亚军国家的编号。

#include<bits/stdc++.h>
using namespace std;
int n;
struct g{
    int num;
    int ant =0;
};
int main()
{
    cin >> n;
    g maxl,maxr;
    g a;
    for(int i=1;i<=pow(2,n)/2;i++){
        cin >> a.ant;
        if(a.ant > maxl.ant){
            maxl.ant = a.ant;
            maxl.num = i;
        }
    }
    for(int i=pow(2,n)/2+1;i<=pow(2,n);i++){
        cin >> a.ant;
        if(a.ant>maxr.ant){
            maxr.ant = a.ant;
            maxr.num = i;
        }
    }
    if(maxl.ant > maxr.ant)
    cout << maxr.num;
    else
    cout << maxl.num;
    
    return 0;
}

思路:把参加的国家均分为两部分,选出前部分最高的能力值和后部分的最高能力值作比较,输出较小的那个就是亚军

(现在想一想,好像不用结构体也可以记录号码,用一个变量来记录就可以了)

P4913 【深基16.例3】二叉树深度

题目描述

有一个 n(n≤106) 个结点的二叉树。给出每个结点的两个子结点编号(均不超过 n),建立一棵二叉树(根节点的编号为 1),如果是叶子结点,则输入 0 。

建好这棵二叉树之后,请求出它的深度。二叉树的深度是指从根节点到叶子结点时,最多经过了几层。

输入格式

第一行一个整数 n,表示结点数。

之后 n 行,第 i 行两个整数 l、r,分别表示结点 i的左右子结点编号。若 l=0 则表示无左子结点,r=0同理。

输出格式

一个整数,表示最大结点深度。

#include<bits/stdc++.h>
using namespace std;
int n;
int maxn =-1;
struct g1{
    int l,r;
}g[1000005];
void dfs(int x,int y)
{
    if(x==0) return;
    maxn = max(maxn,y);
    dfs(g[x].l,y+1);
    dfs(g[x].r,y+1);
}
int main()
{
    cin >> n;
    for(int i=1;i<=n;i++)
    cin >> g[i].l>>g[i].r; 
    dfs(1,1);
    cout << maxn; 
    return 0;
}

这题用到了深度优先和结构体,结构体来记录左右子结点,方便访问

思路就是一条路走到底,之后再返回上一层走上个结点的右子树

每下一层y就+1 ,而maxn 记录最远的一次

P1827 [USACO3.4] 美国血统 American Heritage

题目描述

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

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

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

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

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

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

输入格式

第一行: 树的中序遍历

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

输出格式

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

#include<bits/stdc++.h>
using namespace std;
string a,b;
void dfs(int l1,int l2,int l3,int l4){
    if(l1>l2||l3>l4)
    return;
    for(int i=l1;i<=l2;i++)
    if(a[i]==b[l3]){
        dfs(l1,i-1,l3+1,l3+i-l1);
        dfs(i+1,l2,l3+i-l1+1,l4);
        cout<<a[i];
    }
}
int main()
{
    cin>>a>>b;
    int l=a.size();
    dfs(0,l-1,0,l-1);
    return 0;
}

(俺不会qaq)

题解先放着

P5076 【深基16.例7】普通二叉树(简化版)

题目描述

您需要写一种数据结构,来维护一些数( 都是 10^9以内的数字)的集合,最开始时集合是空的。其中需要提供以下操作,操作次数 q 不超过 10^4:

  1. 查询 x 数的排名(排名定义为比当前数小的数的个数 +1。若有多个相同的数,应输出最小的排名)。

  1. 查询排名为 x 的数。

  1. 求 x 的前驱(前驱定义为小于 x,且最大的数)。若未找到则输出 -2147483647。

  1. 求 x 的后继(后继定义为大于 x,且最小的数)。若未找到则输出 2147483647。

  1. 插入一个数 x。

输入格式

第一行是一个整数 q,表示操作次数。

接下来 q 行,每行两个整数 op,x,分别表示操作序号以及操作的参数 x。

输出格式

输出有若干行。对于操作 1,2,3,4,输出一个整数,表示该操作的结果。

用数组写了一下,过了案例,赶紧去交,没过,狠狠的伤心了(qaq)

(没过我也放在这,当个反例)

#include<bits/stdc++.h>
using namespace std;
int q;
int k=0;
int a[10005];
int one(int y){
    for(int i=1;i<=k;i++)
    {
        if(a[i]==y){
            return i;
        }
    }
}
int two(int y)
{
    return a[y];
}
int three(int y)
{
    for(int i=1;i<=k;i++)
    {
        if(a[i]==y){
            return a[i-1];
        }
    }
    return -2147483647;
}
int four(int y)
{
    for(int i=1;i<=k;i++)
    {
        if(a[i]==y){
            return a[i+1];
        }
    }
    return 2147483647;
}
int main()
{
    cin >> q;
    int x,y;
    for(int i =1;i<=q;i++)
    {
        cin >> x >> y;
        if(x==5)
        {
            k++;
            a[k] = y;
            sort(a+1,a+k+1);
        }
        if(x==1){
            cout << one(y) <<endl;
        }
        if(x==2){
            cout << two(y) << endl;
        }
        if(x==3){
            cout << three(y) << endl;
        }
        if(x==4)
        cout << four(y) <<endl;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值