`
iluoxuan
  • 浏览: 580061 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

6:动态连通性 (并查集)

 
阅读更多

1: 动态连通性

   可以检测所给的点中 是否有环的:

 

 

概念:

  • 并查集:(union-find sets)

一种简单的用途广泛的集合. 并查集是若干个不相交集合,能够实现较快的合并和判断元素所在集合的操作,应用很多,如其求无向图的连通分量个数等。最完美的应用当属:实现Kruskar算法求最小生成树。

  • 并查集的精髓(即它的三种操作,结合实现代码模板进行理解):

1、Make_Set(x) 把每一个元素初始化为一个集合

初始化后每一个元素的父亲节点是它本身,每一个元素的祖先节点也是它本身(也可以根据情况而变)。

2、Find_Set(x) 查找一个元素所在的集合

查找一个元素所在的集合,其精髓是找到这个元素所在集合的祖先!这个才是并查集判断和合并的最终依据。
判断两个元素是否属于同一集合,只要看他们所在集合的祖先是否相同即可。
合并两个集合,也是使一个集合的祖先成为另一个集合的祖先,具体见示意图

3、Union(x,y) 合并x,y所在的两个集合

合并两个不相交集合操作很简单:
利用Find_Set找到其中两个集合的祖先,将一个集合的祖先指向另一个集合的祖先。如图

 

  • 并查集的优化

1、Find_Set(x)时 路径压缩
寻找祖先时我们一般采用递归查找,但是当元素很多亦或是整棵树变为一条链时,每次Find_Set(x)都是O(n)的复杂度,有没有办法减小这个复杂度呢?
答案是肯定的,这就是路径压缩,即当我们经过"递推"找到祖先节点后,"回溯"的时候顺便将它的子孙节点都直接指向祖先,这样以后再次Find_Set(x)时复杂度就变成O(1)了,如下图所示;可见,路径压缩方便了以后的查找。

2、Union(x,y)时 按秩合并
即合并的时候将元素少的集合合并到元素多的集合中,这样合并之后树的高度会相对较小。

 

 

 

 
package com.algorithm.common.tree;

import com.algorithm.lib.StdOut;

/**
 * 动态连通性检查 (并查集算法)
 * @author lijunqing
 */
public class UF {

    /**
     * i节点的父节点(集合)
     */
    private int[] id; // id[i] = parent of i

    /**
     * i集合中子节点数量
     */
    private int[] sz; // sz[i] = number of objects in subtree rooted at i

    /**
     * 集合总数
     */
    private int count; // number of components

    /**
     * 初始化N个集合
     */
    public UF(int N) { // n表示所有数值就是count
        if(N < 0)
            throw new IllegalArgumentException();
        count=N;
        id=new int[N];
        sz=new int[N];
        for(int i=0; i < N; i++) {
            id[i]=i;
            sz[i]=1;
        }
    }

    /**
     * 查找一个元素所在的集合(其精髓是找到这个元素所在集合的祖先) 就是找到改元素所在集合的祖先
     */
    public int find(int p) {
        if(p < 0 || p >= id.length)
            throw new IndexOutOfBoundsException();
        while(p != id[p]) //// 相等表示找到祖先
            p=id[p];
        return p;
    }

    /**
     * 返回集合总数
     */
    public int count() {
        return count;
    }

    /**
     * 判断pq是否在同一集合中
     */
    public boolean connected(int p, int q) {
        return find(p) == find(q);
    }

    /**
     * 合并的时候将元素少的集合合并到元素多的集合中,这样合并之后树的高度会相对较小
     */
    public void union(int p, int q) {
        int i=find(p);
        int j=find(q);
        if(i == j)
            return;

        // make smaller root point to larger one
        if(sz[i] < sz[j]) { // 元素少的集合合并到元素多的集合中
            id[i]=j; // i的父节点是j
            sz[j]+=sz[i];
        } else {
            id[j]=i; // j的父节点是i
            sz[i]+=sz[j]; // 改变父节点的值(值越大表示其子节点越多)
        }
        count--;
    }

    public static void main(String[] args) {
        int N=10;
        UF uf=new UF(N);
        uf.union(1, 2);
        uf.union(3, 4);
        uf.union(6, 7);
        uf.union(2, 7);

        int a=uf.find(6);
        System.out.println(a);

        StdOut.println(uf.count() + " components");
    }

}
 
其中id保存:
  
 0 1 1 3 3 5 1 6 8 9
 
 
分享到:
评论

相关推荐

    12. 并查集-如何快速判断节点连通性1

    并查集是一种高效的数据结构,主要用于处理集合的联通性问题,尤其在判断两个节点是否属于同一个连通分量时表现出色。它由数组构建,数组的下标对应于节点,数组的值则用来表示节点之间的连通关系。下面将详细讨论并...

    并查集入门学习并查集

    - 并查集与树剖、块状链等技术结合,可以用于解决更复杂的动态连通性问题。 综上所述,"并查集入门学习并查集"的资源可能是针对初学者的教程,通过“并查集.pdf”这个文档,你将能够深入理解并查集的基本概念、...

    突破算法极限:并查集如何轻松搞定最棘手的连通性问题?

    《 C++ 修炼全景指南:十五 》突破算法极限:并查集如何轻松搞定最棘手的连通性问题?https://lenyiin.blog.csdn.net/article/details/142865958?spm=1001.2014.3001.5502 这篇博客所涉及的所有完整代码 。本篇...

    图论- 图的连通性- 并查集判断连通性.rar

    在提供的压缩包"图论- 图的连通性- 并查集判断连通性.pdf"中,很可能是详细讲解了如何运用并查集这一数据结构来解决图的连通性问题,包括理论基础、算法实现、实例分析等。通过学习这份资料,你可以深入理解并掌握...

    数据结构并查集 查询 快速

    在实战应用中,如给定的部分代码所示,我们可以看到并查集被用于解决图的连通性判断问题,以及更复杂的敌友关系判断问题。在处理图的连通性时,通过不断执行`union`操作连接相邻节点,最后通过`find`操作检查任意两...

    并查集 团伙数据

    并查集是一种在图论和算法设计中常用的离散数学结构,主要用于处理一些不相交集合的合并与查询问题。这个压缩包文件“团伙数据”显然包含了一些与并查集算法相关的练习数据和可能的题解,目的是帮助学习者更好地理解...

    并查集 第12章 并查集

    **并查集**(Union-Find Set)是一种数据结构,用于处理一些不相交集合的合并及查询问题,通常用来解决动态连通性问题。并查集支持两种主要的操作:**并操作**(Union)和**查找操作**(Find)。并操作用于合并两个...

    并查集大纲资料.txt

    并查集经常被用于需要动态维护一些不相交集合的连通性问题中,如社交网络中判断两个用户是否属于同一社区,或是计算机网络中检测网络的连通性等。此外,算法问题中的路径压缩技术和按秩合并技术是并查集提高效率的...

    并查集基础知识讲解

    在实际应用中,例如判断网络中的两台计算机是否可以直接通信、社交网络中的人际关系分析、无向图的连通性检测等场景,都可以利用并查集来解决问题。并查集的高效性和简洁性使其在算法竞赛和实际编程中都得到了广泛...

    带权并查集模板,从并查集基础拓展

    带权并查集(Weighted Union-Find)是一种在数据结构中用于处理不相交集合(Disjoint Set)的算法,它通过合并过程来减少集合的数量,同时考虑合并操作的权重。以下是一个针对带权并查集模板的资源描述: 资源标题...

    并查集算法PKU解题报告

    并查集是一种用于处理集合合并与查询的抽象数据类型,主要应用于解决连通性问题,例如判断图中的两个节点是否在同一连通分量内。在本解题报告中,我们将探讨并查集算法在PKU(北京大学)的三道题目:PKU1182、PKU...

    并查集学习整理 初学者必备

    5. **应用案例**:并查集常用于解决不相交集合的问题,如判断图中是否存在环、网络连通性问题、社交网络中的朋友关系查询等。在ACM竞赛中,如“连通组件”、“最近公共祖先”等问题中,都能看到并查集的身影。 6. *...

    并查集模版

    并查集是一种用于处理元素集合的动态数据结构,常被应用于图论、计算机网络、数据挖掘等领域。其核心功能是支持两种操作:合并两个集合(并操作)与查询某个元素所属的集合(查操作)。并查集在解决具有高度关联性的...

    检查网络---课程设计-并查集

    并查集是一种在图论和数据结构中广泛使用的算法,主要用来解决网络连通性问题。在这个2010年7月的浙江大学课程设计中,学生们被要求利用并查集来检查网络的连通状态。这是一个典型的离散数学和算法应用的实践任务,...

    并查集问题

    1. poj2524.cpp:这是一个POJ(Problem Setter's Online Judge)的编程题目,通常涉及到特定的算法问题,可能需要利用并查集解决连通性或路径查找问题。 2. hdoj1233最小生成树,克鲁斯卡尔.cpp:最小生成树是图论...

    并查集算法思想的算法

    并查集主要应用于处理动态连通性问题,例如判断两个元素是否属于同一个集合,以及将不属于同一个集合的元素进行合并。 #### 二、等价类及其性质 在讨论并查集之前,我们先了解等价类的相关概念。 1. **等价类**:...

    最经典并查集详细讲解

    并查集是一种在分散的数据... 并查集是一种实用的数据结构,通过高效地处理集合的合并和查询,广泛应用于各种需要处理连通性问题的场景。熟练掌握并查集的原理和实现,对于解决算法竞赛和实际工程问题都具有重要意义。

    优化并查集

    在实际应用中,如网络连接、社交网络分析、图的连通性判断等场景,优化后的并查集能够提供高效的解决方案。测试用例可以设计成一系列的 `Union` 和 `Find` 请求,验证并查集的正确性和性能。 通过理解和熟练掌握...

    并查集_并查集_洛谷_

    并查集是一种在图论和数据结构中常用的算法,主要用于处理一些不相交集合的合并与查询问题。在洛谷这个知名的在线编程平台上有许多关于并查集的例题,这些题目非常适合初学者用来入门并查集的学习。 并查集的主要...

    数据结构--并查集(Union-Find Sets)

    并查集(Union-Find Sets)是数据结构中一种用于管理元素集合的高效算法,它主要处理两个操作:连接(union)与查找(find)。在并查集中,元素被分到不同的集合中,每个集合代表一个独立的组件。连接操作将两个元素...

Global site tag (gtag.js) - Google Analytics