码迷,mamicode.com
首页 > 其他好文 > 详细

并查集

时间:2017-12-02 12:55:43      阅读:125      评论:0      收藏:0      [点我收藏+]

标签:return   就是   查询   while   并集   含义   数组   images   集合   

一、定义

并查集是一种树形的数据结构,用于处理一些不相交集合的合并以及查询问题。

二、操作

1、void make_set(int n)

含义:有n个元素,把这n个元素初始化成n个集合,每个集合包含1个元素。

2、int find_root(int x)

含义:查找元素x所在的集合,返回集合的根结点。通过查找两个元素的根结点是否相同,可以判断两个元素是否属于同一个集合。

3、void union_set(int a, int b)

含义:合并两个不相交的集合。

三、举例

假设有3个元素,编号分别为1,2,3,则进行初始化make_set后,这3个元素形成了3个集合{1},{2},{3},集合之间互不相交,对应的树如下图所示:

技术分享图片

可以看到3个元素形成了3颗独立的树,每颗树只包含一个根结点。我们使用数组p[x]来表示结点x的父结点,若x为根结点,则令p[x]=-1(或者令p[x]=x),所以有p[1]=-1,p[2]=-1,p[3]=-1。合并集合则是将一棵树的根结点变成另一颗树的孩子结点,合并集合{1},{2}后,对应的数如下所示:

技术分享图片

此时有p[1]=-1,p[2]=1,p[3]=-1。再将集合{3}与集合{1,2}合并,则有

技术分享图片

此时p[1]=-1,普p[2]=1,p[3]=1,3个集合最终合并成了一个集合。

四、优化

并查集最初的状态时一个个不相交的集合,如果只是简单的合并而不采取任何优化,那么树高可能会不断增加,最坏的情况是一棵树退化成了一条链,树高越高,查找根结点所花费的时间也就越长我们希望树应该尽可能的低,可以使用下面两种方法来进行优化:

1、路径压缩

在查找某结点x的根结点的过程中,将结点x与根结点和x之间的所有结点都直接指向根结点,这就是路径压缩。如下图:

技术分享图片

代码实现(递归):

//查找根结点时路径压缩,递归实现
int find_root(int x)
{
    if(p[x] == -1)
        return x;
    else 
    {
        int t = find_root(p[x]);
        p[x] = t;
        return t;
    }
}

代码实现(非递归):

//查找根结点时路径压缩,非递归实现
int find(int x)
{
    int k, j, r;
    r = x;
    while(r != parent[r])     //查找跟节点
        r = parent[r];      //找到跟节点,用r记录下
    k = x;        
    while(k != r)             //非递归路径压缩操作
    {
        j = parent[k];         //用j暂存parent[k]的父节点
        parent[k] = r;        //parent[x]指向跟节点
        k = j;                    //k移到父节点
    }
    return r;         //返回根节点的值            
}

2、按秩合并

按秩合并即将元素少的集合合并到元素多的集合中,这样有利于降低树高。

并查集

标签:return   就是   查询   while   并集   含义   数组   images   集合   

原文地址:http://www.cnblogs.com/sench/p/7953768.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!