22计算机408考研—数据结构—并查集

290 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第27天,点击查看活动详情

手把手教学考研大纲范围内树定义,遍历,Huffman,并查集 22考研大纲数据结构要求的是C/C++,笔者以前使用的都是Java,对于C++还很欠缺, 如有什么建议或者不足欢迎大佬评论区或者私信指出 初心是用最简单的语言描述数据结构

Talk is cheap. Show me the code. 理论到处都有,代码加例题自己练习才能真的学会

并查集

并查集介绍

一、概念及其介绍 并查集是一种型的数据结构,用于处理一些不相交集合的合并及查询问题。

并查集的思想是:用一个数组表示了整片森林(parent),树的根节点唯一标识了一个集合,我们只要找到了某个元素的的树根,就能确定它在哪个集合里。

二、适用说明 并查集用在一些有 N 个元素的集合应用问题中,我们通常是在开始时让每个元素构成一个单元素的集合,然后按一定顺序将属于同一组的元素所在的集合合并,其间要反复查找一个元素在哪个集合中。这个过程看似并不复杂,但数据量极大,若用其他的数据结构来描述的话,往往在空间上过大,计算机无法承受,也无法在短时间内计算出结果,所以只能用并查集来处理。

三、并查集的基本数据表示

在这里插入图片描述

如上图 0-4 下面都是 0,5-9 下面都是 1, 表示 0、1、2、3、4 这五个元素是相连接的,5、6、7、8、9 这五个元素是相连的。

在这里插入图片描述

再如上图 0、2、4、6、8 下面都是 0 这个集合,表示 0、2、4、6、8 这五个元素是相连接的 1、3、5、7、9 下面都是 1 这个集合,表示 0,1、3、5、7、9 这五个元素是相连的。

Talk is cheap, Show me the Code. 用下面的例题,趁热打铁练习一下层序遍历

并查集例题

题目链接(洛谷:P1551 亲戚) 在这里插入图片描述

思路: 因为并查集是根据森林处理问题 每个集合就是一个森林,此题把两个集合合起来, 换句话说把每个森林的头结连起来,把一个森林的头结点添加到另一个森林头结点的子结点(把两个森林合起来

#include "iostream"

using namespace std;

int f[10001];

    //找a结点的祖先
int getfather(int a) {
    if (f[a] == a) {    //如果a的父亲是自己,证明a的祖先就是a,返回a
        return a;
    } else {    //如果a的父亲不是自己
                //就把a的父亲的父亲求出来赋值给a的父亲,f[a]将变成a的爷爷
    // 不断重复调用并赋值给f[a],f[a]将快要变成a的祖先(f[a]不一定是祖先,但是接近祖先)
        return f[a] = getfather(f[a]);
    }
}

    //把 a 与 b 联系起来
void hb(int a, int b) { //a的祖先的父亲变成b的祖先(把两个森林(集合)联系起来)
    f[getfather(a)] = getfather(b);
}

int main() {
    int n, m, p, a, b;
    cin >> n >> m >> p;
    for (int i = 1; i <= n; i++) {
        f[i] = i;
    }
    for (int i = 0; i < m; i++) {
        cin >> a >> b;
        hb(a, b);   //合并 a 和 b
    }
    for (int i = 0; i < p; i++) {
        cin >> a >> b;
        if (getfather(a) == getfather(b)) { // 看 a b 的祖先是否相等
            cout << "Yes" << endl;
        } else {
            cout << "No" << endl;
        }
    }
    return 0;
}