不相交集合数据结构或并查集算法介绍

不相交集合数据结构或并查集算法介绍

不相交集信息结构,也称为并查算法,可能是计算机科学中的一个基本概念,它为解决与分配和网络相关的问题提供了有效的方法。它对于解决包括组件集和确定它们的连接在内的问题特别有价值。在本文中,我们将研究语言结构、算法以及在 C++ 中执行不相交集合信息结构的两种独特方法。我们还将提供完全可执行的代码示例来说明这些方法。

语法

在深入研究算法之前,让我们先熟悉一下以下代码示例中使用的语法 –

// Create a disjoint setDisjointSet ds(n);// Perform union operationds.unionSets(a, b);// Find the representative of a setds.findSet(x);

算法

处理多个不关联的集合时,利用不相交的数据结构可能非常有用。每个单独的分组都指定有一个特定的代表来表征它。起点涉及每个组件形成其自己的隔离集,该隔离集与其各自的代表相对应(也恰好是其自身)。对不相交集执行的两个主要操作是并集和查找。

联合操作

找到要合并的两个集合的代表。

如果代表不同,则使一个代表指向另一个代表,有效地合并集合。

如果代表是相同的,则集合已经合并,不需要进一步操作。

查找操作

给定一个元素,找到它所属集合的代表。

跟随父指针直到达到代表节点。

将代表作为结果返回。

方法一:基于排名的按秩合并和路径压缩

实现不相交集数据结构的一种有效方法是使用按等级并集和路径压缩技术。

在此方法中,每个集合都有一个关联的排名,最初设置为 0。

在两个集合之间执行并集运算时,优先考虑排名较高的集合,并合并排名较低的集合。如果两个集合具有相似的等级,则必须任意选择哪个集合包含谁。在任何一种情况下,一旦合并到新集合中,其排名都会增加 1。此外,为了加快查找操作并降低时间复杂度,路径压缩有助于在这些操作期间压平树结构。

Example

的中文翻译为:

示例

#include #include class DisjointSet {   std::vector parent;   std::vector rank;    public:   DisjointSet(int n) {      parent.resize(n);      rank.resize(n, 0);      for (int i = 0; i < n; ++i)         parent[i] = i;   }       int findSet(int x) {      if (parent[x] != x)         parent[x] = findSet(parent[x]);      return parent[x];   }       void unionSets(int x, int y) {      int xRoot = findSet(x);      int yRoot = findSet(y);              if (xRoot == yRoot)         return;              if (rank[xRoot]  rank[yRoot])         parent[yRoot] = xRoot;      else {         parent[yRoot] = xRoot;         rank[xRoot]++;      }   }};int main() {   // Example usage of DisjointSet   int n = 5;  // Number of elements   DisjointSet ds(n);   ds.unionSets(0, 1);   ds.unionSets(2, 3);   ds.unionSets(3, 4);   std::cout << ds.findSet(0) << std::endl;     std::cout << ds.findSet(2) << std::endl;     return 0;}

输出

02

方法 2:通过大小和路径压缩进行基于大小的合并

另一种处理不相交集合数据结构的方法是使用按大小合并和路径压缩技术。

在此方法中,每个集合都有一个关联的大小,最初设置为 1。

在并集操作中,较小的集合被合并到较大的集合中。

结果集的大小会相应更新。

在查找操作期间应用路径压缩以展平树结构,类似于之前的方法。

Example

的中文翻译为:

示例

#include #include class DisjointSet {   std::vector parent;   std::vector size;    public:   DisjointSet(int n) {      parent.resize(n);      size.resize(n, 1);      for (int i = 0; i < n; ++i)         parent[i] = i;   }       int findSet(int x) {      if (parent[x] != x)         parent[x] = findSet(parent[x]);      return parent[x];   }       void unionSets(int x, int y) {      int xRoot = findSet(x);      int yRoot = findSet(y);              if (xRoot == yRoot)         return;              if (size[xRoot] < size[yRoot]) {         parent[xRoot] = yRoot;         size[yRoot] += size[xRoot];      }      else {         parent[yRoot] = xRoot;         size[xRoot] += size[yRoot];      }   }};int main() {   // Example usage of DisjointSet   int n = 5;  // Number of elements   DisjointSet ds(n);   ds.unionSets(0, 1);   ds.unionSets(2, 3);   ds.unionSets(3, 4);   std::cout << ds.findSet(0) << std::endl;     std::cout << ds.findSet(2) << std::endl;     return 0;}

输出

02

结论

不相交集合数据结构或并查算法是解决涉及集合和连通性问题的强大工具。本文广泛研究了 C++ 的不相交集数据结构语法及其算法。为了扩展我们的理解,我们为读者提供了两种独特的方法 – 基于排名的并集与路径压缩相结合,以及通过大小加路径压缩进行基于大小的并集。通过理解和实现这些方法,您可以有效地解决需要跟踪不相交集的各种问题。

以上就是不相交集合数据结构或并查集算法介绍的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1444938.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年12月17日 22:02:01
下一篇 2025年12月17日 22:02:11

相关推荐

  • 数据结构在前端的应用_树形结构的遍历与搜索

    树形结构遍历分为深度优先(DFS)和广度优先(BFS);DFS按访问根节点时机分为前序、中序、后序,分别适用于复制树、获取有序序列、计算子节点依赖场景;BFS通过队列实现层序访问,适合查找最短路径或最近匹配;搜索时可基于DFS或BFS框架,在节点访问时加入条件判断,如根据aname查找“袁隆平”节点…

    2025年12月21日
    000
  • JavaScript数据结构_javascript算法基础

    掌握JavaScript数据结构与算法需从数组、对象、Map、Set、栈、队列入手,理解其操作与时间复杂度;1. 数组适合读取多于修改的场景,索引访问O(1),中间增删O(n);2. 对象键限字符串或Symbol,Map支持任意键且遍历有序,查找、插入、删除平均O(1);3. Set自动去重,增删查…

    2025年12月21日
    000
  • JavaScript树结构操作_javascript数据结构

    树结构是前端处理层级数据的核心,通过对象实现节点与子节点关联。掌握深度优先(DFS)、广度优先(BFS)遍历、查找、增删节点及扁平化等操作,能高效处理菜单、组织架构等场景。1. DFS递归访问子树;2. BFS使用队列按层遍历;3. 查找节点需递归匹配id;4. 添加节点前需定位父级并初始化chil…

    2025年12月21日
    000
  • js中pop和push的比较

    push方法向数组末尾添加元素,返回新长度;pop方法移除并返回最后一个元素;两者均改变原数组,常用于栈结构操作。 push 和 pop 都是 JavaScript 中数组的方法,用于在数组的末尾添加或删除元素。它们都直接修改原数组(即会改变数组的长度),并且返回值不同,用途也不同。 1. push…

    2025年12月21日
    000
  • JavaScript中的数据结构(如链表、树)如何实现与应用?

    JavaScript中可通过对象和引用实现链表与二叉树。链表由节点(数据+指针)构成,适合频繁增删场景,如队列、大数相加、浏览器历史;双向链表结合哈希可实现LRU缓存。二叉树用于搜索、表达式解析等,支持前序(复制)、中序(有序输出)、后序(释放节点)遍历,可用递归或栈实现。DOM树、状态管理、层级数…

    2025年12月20日
    000
  • JavaScript中的Map和Set数据结构

    Map和Set是ES6引入的数据结构,Map支持任意类型键、保持插入顺序且性能更优,适用于非字符串键或需高效增删的场景;Set确保值唯一,适合去重和高效查找。与对象相比,Map避免了键的隐式转换,提供更可靠的键值对管理;Set通过has()实现O(1)查找,远快于数组includes()。高级用法包…

    2025年12月20日
    000
  • 如何实现一个支持LRU缓存算法的数据结构?

    答案:结合哈希表和双向链表实现LRU缓存,哈希表支持O(1)查找,双向链表维护访问顺序,头结点为最近使用,尾结点为最久未使用;get操作查找不到返回-1,找到则移到头部并返回值;put操作若键存在则更新并移至头部,否则创建新节点插入头部,超容量时删除尾部节点;通过add_to_head、remove…

    2025年12月20日
    000
  • JS 数据结构实现指南 – 链表、栈、队列与哈希表的应用场景

    链表、栈、队列与哈希表在JavaScript中通过对象和数组模拟实现,各自适用于不同场景:链表适合频繁增删的动态数据,如LRU缓存;栈遵循LIFO原则,用于函数调用、撤销操作;队列遵循FIFO,适用于任务调度与事件循环;哈希表(Map/对象)提供键值对快速访问,广泛用于缓存、状态管理。性能上,链表插…

    2025年12月20日
    100
  • 如何理解递归?递归在数据结构中的应用

    递归通过函数调用自身将问题分解为更小的子问题,直至达到可直接求解的基本情况。核心包含两部分:基本情况(Base Case)确保递归终止,防止无限循环;递归步骤(Recursive Step)将原问题拆解为更小的同类子问题。以阶乘为例,n == 0 为基本情况,n * factorial(n-1) 为…

    2025年12月20日
    000
  • 什么是红黑树?红黑树的特点和用途

    红黑树的五大核心特性是:1. 每个节点非红即黑;2. 根节点为黑色;3. 红色节点的子节点必须是黑色,即不存在连续的红色节点;4. 从任一节点到其所有叶子节点的路径包含相同数量的黑色节点,保证黑色高度一致;5. 所有空叶子节点(nil节点)均为黑色;这些规则共同确保了红黑树的自平衡性,使其在插入、删…

    2025年12月20日
    000
  • 堆数据结构是什么?堆的特点和用途

    堆和二叉搜索树的主要区别在于:堆用于快速访问最大或最小元素,仅保证父节点与子节点间的大小关系,不维护全局有序,适合优先队列;而二叉搜索树通过左小右大的结构实现有序,支持高效查找、插入和删除,适合查找特定值;因此堆适用于极值操作,bst适用于有序数据操作,两者在应用场景上各有侧重,堆排序的时间复杂度为…

    2025年12月20日
    000
  • C++访问者模式 数据结构与操作分离

    访问者模式通过分离数据结构与操作,实现对表达式树的求值与打印:Expression定义accept方法,ConcreteElement(Number、Addition)实现accept并调用Visitor的visit,Visitor定义visit接口,ConcreteVisitor(Evaluate…

    2025年12月18日
    000
  • 如何实现C++图书管理系统 文件读写与数据结构设计

    实现c++++图书管理系统,核心在于设计合适的数据结构与文件读写机制。1. 首先定义book结构体,包含isbn、书名、作者等基本属性,便于组织每本书的信息;2. 使用std::vector作为初始容器管理图书,适合小规模数据的添加、查找和遍历操作;3. 若需高效查找(如通过isbn),可选用std…

    2025年12月18日 好文分享
    000
  • C++ STL容器如何选择最佳数据结构 对比vector list deque适用场景

    选择c++++ stl容器应根据数据访问模式、插入删除位置、内存管理及数据量大小等因素综合判断。1. vector适用于随机访问频繁、中间插入删除较少的场景,底层为动态数组,内存不足时重新分配影响性能;2. list适合频繁在任意位置插入删除的场景,基于双向链表实现,但随机访问效率低;3. dequ…

    2025年12月18日 好文分享
    000
  • 什么是C++中的内存对齐?

    c++++中的内存对齐是一种编译器优化技术,通过让数据在内存中的起始地址成为特定值(通常是2的幂)的倍数来提高数据访问效率。具体来说,内存对齐的主要原因是现代cpu以字为单位访问内存,如果数据地址不是字大小的倍数,cpu可能需要两次访问,降低执行效率。例如,一个结构体struct example {…

    2025年12月18日
    000
  • C语言数据结构:数据结构在人工智能中的关键作用

    C 语言数据结构:数据结构在人工智能中的关键作用 概述 在人工智能领域,数据结构对于处理大量数据至关重要。数据结构提供了一种组织和管理数据的有效方法,优化算法和提高程序的效率。 常见的数据结构 立即学习“C语言免费学习笔记(深入)”; C 语言中常用的数据结构包括: 数组:一组连续存储的数据项,具有…

    2025年12月18日
    000
  • C语言数据结构:常见面试问题剖析

    数据结构是 c 语言面试中的关键知识点:指针和数组:理解指针指向数组起始地址并用于访问和修改数组元素。链表:实现单向链表,掌握创建、插入和删除操作。栈:利用数组构建栈,理解压栈、出栈和查看栈顶操作。队列:使用数组实现队列,掌握入队、出队和查看队首操作。 C 语言数据结构:常见面试问题剖析 在许多编程…

    2025年12月18日
    000
  • C语言数据结构:数据结构在图像处理中的运用

    数据结构在图像处理中至关重要,c语言提供了数组、链表、栈和队列等数据结构。数组用于存储图像数据,链表用于表示边缘或轮廓,栈用于存储操作历史记录,队列用于存储中间结果。实际应用包括使用数组实现灰度图像直方图和使用链表实现图像边缘检测。 C语言数据结构:数据结构在图像处理中的运用 在图像处理中,数据结构…

    2025年12月18日
    000
  • C语言数据结构:数据结构在软件工程中的重要性

    数据结构在软件工程中的重要性在于:组织数据,提高存储效率。优化数据访问,加快检索速度。有效管理内存,降低资源占用。提供系统可扩展性,支持数据增减操作。影响算法效率,根据操作选择合适的数据结构。 C语言数据结构:在软件工程中的重要性 在软件工程中,数据结构对于组织和存储数据至关重要,以确保数据的有效和…

    2025年12月18日
    000
  • C语言算法:常见数据结构与算法详解

    c语言程序中常用的数据结构包括数组、链表、栈和队列。此外,还提供了搜索算法(线性搜索和二分搜索)、排序算法(冒泡排序和选择排序)、图遍历算法(广度优先搜索和深度优先搜索)等一系列算法。这些数据结构和算法的应用,可以大大优化代码性能,简化问题求解。 C语言算法:常见数据结构与算法详解 引言 数据结构是…

    2025年12月18日
    000

发表回复

登录后才能评论
关注微信