并查集---一点小的感悟

 

 

最近在做ACM题,遇到了一个叫做并查集的东西,于是从网上找了一些资料,顺便自己总结了一些,希望对大家和自己都有用~~

    (一)什么叫做并查集

    英文:Disjoint Set,即“不相交集合”  

    将编号分别为1NN个对象划分为不相交集合,在每个集合中,选择其中某个元素代表所在集合。

         常见两种操作:

     1n合并两个集合

     2n查找某元素属于哪个集合

例如,并查集一般用数组来实现,用数组的下标序号作为其元素的代号,其中的每个元素都属于一个集合,初始条件下每个元素所属的集合中只有其一个元素,例如对于元素i来说,其所属的集合为Set[i],在实际应用中要将各个集合进行合并,用编号最小的元素的下标作为整个集合的代号。

用编号最小的元素标记所在集合;

定义一个数组 set[1..n] ,其中set[i] 表示元素i 所在的集合;

         例如上图中,目前元素137都属于集合1,也就是set[1]=set[3]=set[7]=1;同理,元素25910都属于集合2,等等。用数学语言描述,不相交的集合共有四个: {1,3,7}, {4}, {2,5,9,10}, {6,8}

上面的算法的实现过程如下:

其中,左图表示查找相应元素所在的集合,右图表示将两个集合相合并,当然前提条件是参数ab分别表示的是集合。其复杂度不难计算出来:右图中的算法包括一个循环,此循环的复杂度为O(N),当元素的个数很少是还能接受,但是当元素的个数很多时,其运算速度很难让人接受。

为了改进合并算法,将元素用树的形式表示出来:

每个集合用一棵有根树表示

定义数组 set[1..n]

set[i] = i , i表示本集合,并是集合对应树的根

set[i] = j, j<>i, j i 的父节点.

下面是其算法

从树中的每个节点开始顺着其父节点向上查找,直到找到其相应的根节点。

其复杂度算法也是容易算出的,先说查找算法:当树是一个左偏树或者右偏树时,其复杂度为O(N),但是当树为一个普通的树时,其复杂度为从此节点到其根节点的层数的复杂度,其复杂度为      。合并的算法的复杂度为O(1);

由于合并的时候是随机合并的,因此容易形成左偏树或者右偏树,这样不利于降低查找算法的复杂度,为了节省算法开销,作如下的改进。

方法:将深度小的树合并到深度大的树

实现:假设两棵树的深度分别为h1h2, 则合并后的树的高度h:

max(h1,h2), if h1<>h2.

h1+1, if h1=h2.

效果:任意顺序的合并操作以后,包含k个节点的树的最大高度不超过

其算法如下所示:

为了进一步优化算法,可以进行路径压缩:

思想:每次查找的时候,如果路径较长,则修改信息,以便下次查找的时候速度更快

步骤:

第一步,找到根结点

第二步,修改查找路径上的所有节点,将它们都指向根结点

算法如下:

         

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值