首页 > 其他分享 >【数据结构机试】树

【数据结构机试】树

时间:2023-08-27 14:00:15浏览次数:36  
标签:rt 26 now int mp l1 机试 数据结构

存储 & 访问

一般的树

vector<int> v[N];

void dfs(int u) {
  for(auto x : v[u]) {
    ...
    dfs(x);
  }
}

二叉树

int L[N], R[N];  // 表示左右儿子的值分别是多少

至于编号,结点 \(i\) 的左儿子 \(2i\),右儿子 \(2i+1\)

树的遍历

一般的数

分为先根(先访问根,后访问儿子)、后根(先访问儿子,后访问根)。

二叉树

先序遍历(根左右)、中序遍历(左根右)、后序遍历(左右根)。

例1
PTA 1119 Pre- and Post-order Traversals

题意

给你先序和后序遍历序列,判断二叉树形态是否唯一。

解答

首先知道先序的构成:序列第一个数是根,然后依次是根的左子树和右子树,根在后序序列中位于最后一个;
先序第二个元素,是根的左儿子(除非根没有左儿子,那么是根的右儿子);
我们可以找到在后序序列中 先序第二个元素的位置 \(p\),在先序序列中,从 \(p-1\) 到正数第二个,这些都是根的左子树, \(p + 1\) 到先序最末尾,这些都是根的右子树,我们由此递归建树。

形态不唯一的情况:对某棵子树的根来说,它只有左儿子无右儿子 或者 只有右儿子无左儿子,那么无论它到底有的是哪个儿子,你会发现,这两种情况对应的先序和后序序列一样,即无法判断,此时就是不唯一的

code
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 3000 + 10;
int n, pre[N], post[N], tem[N];
int rt, L[N], R[N];
map<int, int> mp, Map;
int dfn, ans[N];
bool f = 1;

int solve(int l1, int r1, int l2, int r2) {
    if(l1 > r1 || l2 > r2) return 0;
    if(l1 == r1) return pre[l1];
    int now_rt = pre[l1];
    int now_l = pre[l1 + 1], pos = mp[now_l];
    int cnt_l = pos - l2 + 1, cnt_r = r2 - pos - 1;
    L[now_rt] = solve(l1 + 1, l1 + cnt_l, l2, l2 + cnt_l - 1);
    R[now_rt] = solve(l1 + cnt_l + 1, r1, l2 + cnt_l, r2 - 1);
    if(f && (!L[now_rt] || !R[now_rt]) && (L[now_rt] || R[now_rt])) f = 0;
    return pre[l1];
}

void dfs(int rt) {
    if(L[rt]) dfs(L[rt]);
    ans[++dfn] = rt;
    if(R[rt]) dfs(R[rt]);
}

signed main(){
    ios::sync_with_stdio(false);
    cin >> n;
    for(int i = 1; i <= n; i++) cin >> pre[i], tem[i] = pre[i];
    for(int i = 1; i <= n; i++) cin >> post[i];
    sort(tem + 1, tem + n + 1);
    for(int i = 1; i <= n; i++) {
        int x = pre[i];
        pre[i] = lower_bound(tem + 1, tem + n + 1, pre[i]) - tem;
        Map[pre[i]] = x;
        post[i] = lower_bound(tem + 1, tem + n + 1, post[i]) - tem;
        mp[post[i]] = i;
    }
    if(n == 1) {
        cout << "Yes" << '\n';
        cout << Map[pre[1]] << endl;
        return 0;
    }
    rt = solve(1, n, 1, n);
    dfs(rt);
    cout << (f ? "Yes" : "No") << endl;
    for(int i = 1; i <= dfn; i++) {
        ans[i] = Map[ans[i]];
        if(i == 1) cout << ans[i];
        else cout << ' ' << ans[i];
    }cout << '\n';
	return 0;
} 

LCA

单次询问 \(O(n)\) 复杂度的做法不再赘述。

并查集

当我们只关心结点之间有没有关系时使用

分享一个板子:

点击查看代码
//并查集模板 亲戚 
#include<cstdio>
using namespace std;
int father[5005];

//路径压缩 
int f(int x){
    return x == father[x] ? x : (father[x] = f(father[x]));
}

int add(int x,int y){ 
	int fx=f(x);
	int fy=f(y);
	return father[fx]=fy;  //x.y无序,因为不是按树的结构存储,而是按集合 
}

int main(){
	int n,m,p;
	scanf("%d%d%d",&n,&m,&p);
	for(int i=1;i<=n;i++) father[i]=i;
	for(int i=1;i<=m;i++){
		int x,y;
		scanf("%d%d",&x,&y);
		if(f(x)!=f(y)){
			add(x,y);
		}
	}
	for(int i=1;i<=p;i++){
		int x,y;
		scanf("%d%d",&x,&y);
		if(f(x)==f(y)){
			puts("Yes");
		}
		else puts("No");
	}
	return 0;
}

例1
PTA 1034 Head of a Gang

题意

\(m\) 通电话,给出通话双方和时长(注意,两人之间可能有多次通话),通话过的人属于同一帮人。找到 人数>=3 且 通话总时间(帮派中每两人之间)>=K 的帮派的人数和首领(和其他人通话最长的)

解答

并查集维护,注意要字符串转数字编号,累加两人通话总时间

code
点击查看代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 2000 + 10;
int m, k;
map<string, int> mp;
string a, b;
int tem[N], dfn, ori[N];
struct node{
    int u, v, t;
}peo[N];
int g[N][N]; 
bool vis[N][N];
int fa[N], sz[N], cnt[N];
vector<int> v[N];
int ans[N], id[N];
vector<int> prin;

inline int f(int x){
    return x == fa[x] ? x : (fa[x] = f(fa[x]));
}

void add(int u, int v) {
    int w = g[u][v];
    u = f(u); v = f(v);
    if(u != v) {
        fa[u] = v;
        sz[v] += sz[u] + w;
        cnt[v] += cnt[u];
    }
    else {
        sz[u] += w;
    }
    return;
}

int main(){
    // ios::sync_with_stdio(false);
    cin >> m >> k;
    for(int i = 1; i <= m; i++) {
        cin >> a >> b;
        if(!mp[a]) mp[a] = (a[0] - 'A') * 26 * 26 + (a[1] - 'A') * 26 + (a[2] - 'A') + 1, tem[++dfn] = mp[a];
        if(!mp[b]) mp[b] = (b[0] - 'A') * 26 * 26 + (b[1] - 'A') * 26 + (b[2] - 'A') + 1, tem[++dfn] = mp[b];
        peo[i].u = mp[a]; peo[i].v = mp[b]; cin >> peo[i].t;
    }
    // cout << "dfn: " << dfn << endl;
    sort(tem + 1, tem + dfn + 1);
    for(int i = 1; i <= m; i++) {
        int x = peo[i].u;
        peo[i].u = lower_bound(tem + 1, tem + dfn + 1, peo[i].u) - tem;
        ori[peo[i].u] = x; 

        x = peo[i].v;
        peo[i].v = lower_bound(tem + 1, tem + dfn + 1, peo[i].v) - tem;
        ori[peo[i].v] = x;
        // cout << peo[i].u << ' ' << peo[i].v << endl;  ////
        g[peo[i].u][peo[i].v] += peo[i].t; g[peo[i].v][peo[i].u] += peo[i].t;
    }
    for(int i = 1; i <= dfn; i++) fa[i] = i, cnt[i] = 1, sz[i] = 0;
    for(int i = 1; i <= m; i++) {
        if(vis[peo[i].u][peo[i].v]) continue;
        vis[peo[i].u][peo[i].v] = vis[peo[i].v][peo[i].u] = 1;
        add(peo[i].u, peo[i].v);
        // cout << peo[i].u << ' ' << peo[i].v << ' ' << g[peo[i].u][peo[i].v] << endl;  ////
    }
    set<int> st;
    for(int i = 1; i <= dfn; i++) {
        int p = f(i);
        // cout << p << ' ' << cnt[p] << ' ' << sz[p] << endl;
        if(cnt[p] > 2 && sz[p] > k) st.insert(p), v[p].push_back(i);
    }
    cout << st.size() << endl;
    if(st.empty()) return 0;

    memset(ans, -1, sizeof(ans));
    for(auto i : st) {   // i: predecessor
        for(auto x : v[i]) {   // x: son
            int res = 0;
            for(int j = 1; j <= dfn; j++) {
                res += g[x][j];
            }
            if(res > ans[i]) ans[i] = res, id[i] = x;
        }
        prin.push_back(id[i]);
    }
    sort(prin.begin(), prin.end());
    for(auto i : prin) {
        int tmp = ori[i] - 1;
        string s;
        s += (char)(tmp / (26 * 26) + 'A'); tmp %= (26 * 26);
        s += (char)(tmp / (26) + 'A'); tmp %= (26);
        s += (char)(tmp + 'A');
        cout << s << ' ' << cnt[f(i)] << endl;
    }
	return 0;
} 

AVL树(平衡二叉树)

标签:rt,26,now,int,mp,l1,机试,数据结构
From: https://www.cnblogs.com/re0acm/p/17660187.html

相关文章

  • 「算法与数据结构」梳理6大排序算法 为了offer!
    6种排序如下......
  • GEO数据结构
    概念GEO就是Geolocation的简写形式,代表地理坐标。Redis在3.2版本中加入了对GEO的支持,允许存储地理坐标信息,帮助我们根据经纬度来检索数据。常用命令常见的命令有:GEOADD:添加一个地理空间信息,包含:经度(longitude)、纬度(latitude)、值(member)GEOADDkeylongitudelatitudememb......
  • 数据结构代码题-线性表
    王道数据结构大题代码线性表#include<stdio.h>#include<stdlib.h>voiddelMin(int*arr,intlen){ if(!len){ printf("数组为空"); return0; } intmin=*arr,minPos=0; for(inti=0;i<len;i++){ if(min>*(arr+i)){ min=*(arr+......
  • mysql 深入学习一 数据结构导图
    索引的本质 B-Tree结构 B+Tree结构 Hash结构  MyISAM存储引擎索引实现 innodb存储引擎实现 innodb引擎生成两个文件,将索引文件和数据文件都放在的.ibd文件下(这就是聚集索引)myisam引擎生成三个文件,将索引和数据分开保存分别在.MYD.MYI文件下(这就是非聚......
  • 数据结构的分类
    数据结构分为逻辑结构和存储结构(物理结构)逻辑结构:指数据元素之间逻辑关系的数据结构,这里的逻辑关系是指数据元素之间的前后间关系,与数据在计算机中的存储位置无关。物理结构:指数据的逻辑结构在计算机存储空间中的存放形式称为数据的物理结构,也叫做存储结构。数据的逻辑结构......
  • Python数据结构:哈希表
    哈希散列(哈希)是电脑科学中一种对资料的处理方法,通过某种特定的函数/算法(称为散列函数/算法)将要检索的项与用来检索的索引(称为散列,或者散列值)关联起来,生成一种便于搜索的数据结构(称为散列表)。哈希表是什么哈希表(散列表)是根据键(Key)直接访问内存存储位置的数据结构。根据键(Key)值......
  • 并发数据结构设计演练
    QuestDB是一个时间序列数据库,提供快速的摄取速度、InfluxDB线路协议和PGWire支持以及SQL查询语法。QuestDB主要是用Java编写的,我们学到了很多困难而有趣的教训。我们很高兴与您分享。研究数据结构并发数据结构设计很难。该博客提供了有关构建非常有利于读者的专用并发地图......
  • 数据结构与算法
    数据结构与算法:数据结构是一种组织和存储数据的方式,而算法是解决问题的步骤和规则。数据结构和算法是计算机科学的基石之一,对于编写高效和可维护的代码至关重要。数据结构:数据结构是一种组织和存储数据的方式。常见的数据结构包括数组、链表、栈、队列、树和图等。它们具有不同的......
  • 优化后端系统的计算和存储效率 - 高效算法与数据结构
    在构建后端系统时,高效的算法与数据结构是至关重要的。它们可以显著提升计算和存储效率,从而使系统更稳定、快速且可扩展。本文将介绍一些常见的高效算法和数据结构,以及它们在优化后端系统中的应用。1.哈希表哈希表是一种常用的数据结构,它通过将键映射到一个固定大小的数组中来实......
  • 【数据结构】排序 外部排序
    外部排序不会考算法设计,考相关的概念和排序方法过程等。1.外部排序的基本概念外部排序是指对于记录很多的大文件进行排序时,无法将其完全复制进内存中进行排序,因此需要将外存中的待排记录一部分一部分地调入内存中进行排序,在排序过程中需要进行多次内存外存之间的交换,这种排序方......