数据结构之并查集

本文以计蒜客对并查集的介绍为基础,综合其他文章形成。
并查集(Merge-Find Set),也被称为不相交集合(Disjoint Set),是一种经常会用到的树型结构。一些常见的用途有求连通子图、求最小生成树的 Kruskal 算法和求最近公共祖先(Least Common Ancestors, LCA)等。常用来解决若干的不相交集合的如下几种操作:
1、合并操作,将包含 x 和 y 的集合合并为一个新的集合。
2、查询操作,计算 x 所在的集合。
3、判断两个元素是否属于同一个集合。

通常我们会用有根树来表示集合,树中的每一个结点都对应集合的一个成员,每棵树表示一个集合,如下图两棵树表示两个不相交集合。每个成员都有一条指向父结点的边,整个有根树通过这些指向父结点的边来维护。每棵树的根就是这个集合的代表,并且这个代表的父结点是它自己。
通过这样的表示方法,我们将不相交的集合转化为一个森林,也叫不相交森林,下图表示集合{a,b,c,d}和{e,f,g}构成的不相交森林,其中a,e为集合的代表。


这里写图片描述

通常并查集初始化操作是对每个元素都建立一个只包含该元素的集合,每个成员都是自身所在集合的代表。对上图的初始化如下:

这里写图片描述

在不相交森林中,并查集的查询操作,指的是查找出指定元素所在有根树的根结点是谁。我们可以通过每个指向父结点的边回溯到结点所在有根树的根,也就是对应集合的代表元素。

并查集的合并操作需要用到查询操作的结果。合并两个元素所在的集合,需要首先求出两个元素所在集合的代表元素,也就是结点所在有根树的根结点。接下来将其中一个根结点的父亲设置为另一个根结点。这样我们就把两棵有根树合并成一棵了。合并过程如下:


这里写图片描述

并查集的查询操作在最坏情况发生时,每次合并对应到森林上都是一个点连到一条链的一端,这时时间复杂度为 O(n)O(n),其中 n 为总元素个数。如果每次都查询链的最底端,也就是最远离根的位置的元素时,复杂度便是 O(n)O(n) 了。

为了改善时间效率,可以通过启发式合并方法——按秩合并,秩表示树的高度上界,简单说就是将较矮的树接到较高树的树根上,从而防止树退化成一条链。另外,我们也可以通过路径压缩的方法来进一步减少均摊复杂度。同时使用这两种优化方法,可以将每次操作的时间复杂度优化至接近常数级。
路径压缩指的是在每次查找时,令查找路径上的每个节点都直接指向根节点,如下图:


这里写图片描述

实现并查集的标准代码:

#include <stdio.h>

const int MAXN = 100; /*结点数目上线*/
int pa[MAXN];    /*p[x]表示x的父节点*/
int rank[MAXN];    /*rank[x]是x的高度的一个上界*/

void make_set(int x)
{/*创建一个单元集*/
    pa[x] = x;
    rank[x] = 0;
}

int find_set(int x)
{/*带路径压缩的查找*/
    if(x != pa[x])
        pa[x] = find_set(p[x]);
    return pa[x];
}

/*按秩合并x,y所在的集合*/
void union_set(int x, int y)
{
    x = find_set(x);
    y = find_set(y);
    if(rank[x] > rank[y])/*让rank比较高的作为父结点*/
        pa[y] = x;
    else 
    {
        pa[x] = y;
        if(rank[x] == rank[y])
            rank[y]++;
    }
}

参考文章:
计蒜客-数据结构-并查集;
并查集:http://www.cnblogs.com/cyjb/p/UnionFindSets.html
并查集(不相交集合):http://www.cnblogs.com/ktyanny/archive/2009/12/09/1620043.html

CH341A编程器是一款广泛应用的通用编程设备,尤其在电子工程和嵌入式系统开发领域中,它被用来烧录各种类型的微控制器、存储器和其他IC芯片。这款编程器的最新版本为1.3,它的一个显著特点是增加了对25Q256等32M芯片的支持。 25Q256是一种串行EEPROM(电可擦可编程只读存储器)芯片,通常用于存储程序代码、配置数据或其他非易失性信息。32M在这里指的是存储容量,即该芯片可以存储32兆位(Mbit)的数据,换算成字节数就是4MB。这种大容量的存储器在许多嵌入式系统中都有应用,例如汽车电子、工业控制、消费电子设备等。 CH341A编程器的1.3版更新,意味着它可以与更多的芯片型号兼容,特别是针对32M容量的芯片进行了优化,提高了编程效率和稳定性。26系列芯片通常指的是Microchip公司的25系列SPI(串行外围接口)EEPROM产品线,这些芯片广泛应用于各种需要小体积、低功耗和非易失性存储的应用场景。 全功能版的CH341A编程器不仅支持25Q256,还支持其他大容量芯片,这意味着它具有广泛的兼容性,能够满足不同项目的需求。这包括但不限于微控制器、EPROM、EEPROM、闪存、逻辑门电路等多种类型芯片的编程。 使用CH341A编程器进行编程操作时,首先需要将设备通过USB连接到计算机,然后安装相应的驱动程序和编程软件。在本例中,压缩包中的"CH341A_1.30"很可能是编程软件的安装程序。安装后,用户可以通过软件界面选择需要编程的芯片类型,加载待烧录的固件或数据,然后执行编程操作。编程过程中需要注意的是,确保正确设置芯片的电压、时钟频率等参数,以防止损坏芯片。 CH341A编程器1.3版是面向电子爱好者和专业工程师的一款实用工具,其强大的兼容性和易用性使其在众多编程器中脱颖而出。对于需要处理25Q256等32M芯片的项目,或者26系列芯片的编程工作,CH341A编程器是理想的选择。通过持续的软件更新和升级,它保持了与现代电子技术同步,确保用户能方便地对各种芯片进行编程和调试。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值