您的位置:首页 > 娱乐 > 八卦 > 【高阶数据结构】——并查集:高效地管理集合

【高阶数据结构】——并查集:高效地管理集合

2024/12/23 5:48:59 来源:https://blog.csdn.net/2301_80220607/article/details/141608614  浏览:    关键词:【高阶数据结构】——并查集:高效地管理集合

前言:

前面我们已经学习了简单的数据结构,包括栈与队列、二叉树、红黑树等等,今天我们继续数据结构的学习,但是难度上会逐渐增大,在高阶数据结构中我们要学习的重点是图等

目录

并查集的原理

并查集的基本操作

实现方式

C++实现

C语言实现


并查集的原理

并查集(Disjoint-Set Data Structure)是一种用于管理集合的高效数据结构,特别适用于处理“动态连接”的问题,即动态地合并集合或查询两个元素是否属于同一个集合。并查集在计算机科学中有着广泛的应用,如用于解决最小生成树问题(Prim算法和Kruskal算法)、解决网络连通性问题、解决图论中的问题等。

并查集的基本操作

并查集主要支持以下三种基本操作:

  1. 查找(Find):确定一个元素属于哪个集合。
  2. 合并(Union):将两个集合合并为一个集合。
  3. 初始化(Init):为每个元素创建一个独立的集合。

实现方式

并查集有两种常见的实现方式:路径压缩和按秩合并。

  • 路径压缩:在查找操作中,将查找路径上的所有节点的父节点直接指向根节点,以减少查找路径的深度。
  • 按秩合并:在合并操作中,将秩较小的集合合并到秩较大的集合中,以减少树的高度。

C++实现

#include <iostream>
#include <vector>class UnionFind {
private:std::vector<int> parent;std::vector<int> rank;public:UnionFind(int n) : parent(n), rank(n) {for (int i = 0; i < n; ++i) {parent[i] = i;rank[i] = 1;}}int find(int x) {if (parent[x] != x) {parent[x] = find(parent[x]); // 路径压缩}return parent[x];}void unite(int x, int y) {int rootX = find(x);int rootY = find(y);if (rootX == rootY) return;if (rank[rootX] > rank[rootY]) {parent[rootY] = rootX;} else if (rank[rootX] < rank[rootY]) {parent[rootX] = rootY;} else {parent[rootY] = rootX;rank[rootX] += 1;}}bool connected(int x, int y) {return find(x) == find(y);}
};int main() {int n, m;std::cin >> n >> m;UnionFind uf(n);for (int i = 0; i < m; ++i) {int a, b;std::cin >> a >> b;uf.unite(a - 1, b - 1); // 转换为0-based索引}for (int i = 0; i < m; ++i) {int a, b;std::cin >> a >> b;std::cout << (uf.connected(a - 1, b - 1) ? "YES" : "NO") << std::endl;}return 0;
}

C语言实现

#include <stdio.h>
#include <stdlib.h>typedef struct {int parent[10001];int rank[10001];
} UnionFind;void init(UnionFind *uf, int n) {for (int i = 0; i <= n; ++i) {uf->parent[i] = i;uf->rank[i] = 1;}
}int find(UnionFind *uf, int x) {if (uf->parent[x] != x) {uf->parent[x] = find(uf, uf->parent[x]); // 路径压缩}return uf->parent[x];
}void unite(UnionFind *uf, int x, int y) {int rootX = find(uf, x);int rootY = find(uf, y);if (rootX == rootY) return;if (uf->rank[rootX] > uf->rank[rootY]) {uf->parent[rootY] = rootX;} else if (uf->rank[rootX] < uf->rank[rootY]) {uf->parent[rootX] = rootY;} else {uf->parent[rootY] = rootX;uf->rank[rootX] += 1;}
}int main() {int n, m;scanf("%d %d", &n, &m);UnionFind uf;init(&uf, n);for (int i = 0; i < m; ++i) {int a, b;scanf("%d %d", &a, &b);unite(&uf, a - 1, b - 1); // 转换为0-based索引}for (int i = 0; i < m; ++i) {int a, b;scanf("%d %d", &a, &b);if (find(&uf, a - 1) == find(&uf, b - 1)) {printf("YES\\n");} else {printf("NO\\n");}}return 0;
}

通过上述C++和C语言的实现,我们可以看到并查集的基本操作和逻辑在不同语言中的实现方式。这两种语言的实现都遵循了并查集的核心思想,即通过查找和合并操作来管理集合,以高效地处理动态连接问题。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com