数据结构之并查集

本文介绍了数据结构中的并查集,一种用于处理集合合并与查找问题的数据结构。并查集主要用于判断两个元素是否属于同一集合,常用于解决亲戚关系查询等问题。通过树结构实现,并查集可以高效地进行查找和合并操作,保持树的平衡以提高性能。文章详细阐述了并查集的初始化、查找和合并操作,并提供了相应的C++代码实现。
摘要由CSDN通过智能技术生成

数据结构中的并查集

一、并查集的概念

1.合并、查找、集合

当给出两个元素的一个无序对(a,b)时,需要快速“合并”a和b分别所在的集合,这期间需要反复“查找”某元素所在的集合。

2.概念

在这数据类型中,n个不同元素被分为若干组。每组是一个集合,这种集合叫分离集合,称之为并查集。

二、并查集典型案例

1.问题

A与B是亲戚,B与C是亲戚,问A与C是否为亲戚?

2.问题分析

亲戚关系是一种典型的等价关系。现将构建一个图论模型,每一个人抽象为一个顶点,N个人即N个顶点,输入的亲戚关系数据则抽象为边,M个亲戚关系数据则为N条边,则可抽象为一个(N,M)图模型。最后的问题则为两个顶点是否在同一个连通块中。

3.思路

在这里插入图片描述

(1)对N个人都建立一个集合,在图中则画出N个孤立顶点。
(2)每给一个亲戚关系,就将所对应的集合合并,在图中则给关联顶点连边。
(3)最后的提问,则查看两个元素是否在同一个集合中,在图上是否在同一个通路上。

4.特点(从集合论的角度)

(1)操作是在集合的基础上进行的,没必要保存所有的边。
(2)每一步的得到的划分方式是动态的。

三、并查集的运算

编号1~n的n个元素,x是其中一个元素,设并查集为S。

1.初始化并查集

S={S1,S2,···,Sn},每一个动态集合Si(1<=i<=n)仅仅包含一个编号为i的元素,该元素作为集合Si的“代表”。

2.查找x元素所在的集合

返回并查集S中x元素所在集合的代表。

3.合并集合

将S中元素x和y所在的动态集合进行合并成一个新的集合,且合并之前元素x和y所在的动态集合是分离的。

四、算法实现

1.实现方法(树实现)

(1)用有根树表示集合,树中的每一个结点包含集合的一个元素,每一棵树表示一个集合。并查集S为森林,每棵树根作为集合的代表,每棵树均有指向双亲的指针parent,根结点的双亲指针指向自身。
注:树中的指针只是联系集合元素的关系的作用,没有从属关系。
在这里插入图片描述

(2)将高度较小的分离集合树作为子树,保证构造的分离集合树高度较低,不会超过log2 n,得到比较平衡的树。
在这里插入图片描述

2.实现代码

(1)数根结点结构体

typedef struct node{
    int data;                  //对应编号
    int rank;                  //对应的秩
    int parent;                //双亲指针
}UFSTree;

其中的秩是近似等于树的高度,用于的树的合并。

(2)并查集初始化

void MAKE_SET(UFSTree t[],int n){
    for(int i=0;i<=n;i++){
        t[i].data=i;
        t[i].rank=0;
        t[i].parent=i;
    }
}

树的高度(秩)为0,编号为i,双亲指针指向自己。

(3)查找元素x所在的集合

int FIND_SET(UFSTree t[],int x){
    if(x!=t[x].parent) return(FIND_SET(t,t[x].parent));
    else return(x);
}

找到x所在节点,沿双亲指针找到根结点,双方的节点编号比下方大(秩),除了根结点的双亲指针与编号相等。

(4)合并集合

void UNION(UFSTree t[],int x,int y){
    x=Find_SET(t,x);
    y=FIND_SET(t,y);

    if(t[x].rank>t[y].rank) t[y].parent=x;
    else{
        t[x].parent=y;
        if(t[x].rank==t[y].rank) t[y].rank++;
    }
}

秩较小的根双亲指针指向秩较大的根,相等时,只需其中一个指向另一个,合并后的树秩加1.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

有几何

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值