Quick-Union[Algorithm]

Google面试题 图论的问题 这道题目摘自九章算法   https://www.jiuzhang.com/article/6ai0yN/ 题目是 输入与输出     这个题目本质上就是删除一个使该图内部成环的一条边,使整个图中不存在环。 这个题目我认为原文的解释有点复杂,最快的方法就是操作数组,角标代表一个顶点,角标所对应的数组的数值代表一个顶点,而角标到该角标数值的对应,我们认为是角标代表的顶点到这个数值... 阅读详情

Q. Is there a path connecting p and q ? 



Quick-Union算法主要提供两个方法:

  • Union:连接两个点
  • Connected:判断两个点是否相连
假定有N个点,用数组int array[N]表示这一集合。用树结构保存两个点的连接信息,array[i]表示点i的父亲节点,root(i)返回点i的根节点。
初始化,每个点的根节点为自己本身。



在经过几次Union操作后,树结构如下图所示(注意数组内容的变化)。此时array[3]=4,表示点3的父节点是点4,root(3)=9。

通过以上分析,我们可以得出Connected的实现方法:
  • root(p) == root(q)则说明p与q相连
  • root(p) != root(q)则说明p与q不相连
而Union(p,q)操作,只要把root(p)的根节点指向root(q)即可。在上述例子中,若操作Union(3,5),因为root(3) =9,root(5)=6,所以修改array[9]=6即达到了9的根节点变为6的目的。
Quick-Union算法的具体实现如下:
/****************************************************************************
 *  Compilation:  javac QuickUnionUF.java
 *  Execution:  java QuickUnionUF < input.txt
 *  Dependencies: StdIn.java StdOut.java
 *
 *  Quick-union algorithm.
 *
 ****************************************************************************/

/**
 *  The <tt>QuickUnionUF</tt> class represents a union-find data structure.
 *  It supports the <em>union</em> and <em>find</em> operations, along with
 *  methods for determinig whether two objects are in the same component
 *  and the total number of components.
 *  <p>
 *  This implementation uses quick union.
 *  Initializing a data structure with <em>N</em> objects takes linear time.
 *  Afterwards, <em>union</em>, <em>find</em>, and <em>connected</em> take
 *  time linear time (in the worst case) and <em>count</em> takes constant
 *  time.
 *  <p>
 *  For additional documentation, see <a href="http://algs4.cs.princeton.edu/15uf">Section 1.5</a> of
 *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.
 *     
 *  @author Robert Sedgewick
 *  @author Kevin Wayne
 */
public class QuickUnionUF {
    private int[] id;    // id[i] = parent of i
    private int count;   // number of components

    /**
     * Initializes an empty union-find data structure with N isolated components 0 through N-1.
     * @throws java.lang.IllegalArgumentException if N < 0
     * @param N the number of objects
     */
    public QuickUnionUF(int N) {
        id = new int[N];
        count = N;
        for (int i = 0; i < N; i++) {
            id[i] = i;
        }
    }

    /**
     * Returns the number of components.
     * @return the number of components (between 1 and N)
     */
    public int count() {
        return count;
    }

    /**
     * Returns the component identifier for the component containing site <tt>p</tt>.
     * @param p the integer representing one site
     * @return the component identifier for the component containing site <tt>p</tt>
     * @throws java.lang.IndexOutOfBoundsException unless 0 <= p < N
     */
    public int find(int p) {
        while (p != id[p])
            p = id[p];
        return p;
    }

    /**
     * Are the two sites <tt>p</tt> and <tt>q</tt> in the same component?
     * @param p the integer representing one site
     * @param q the integer representing the other site
     * @return <tt>true</tt> if the sites <tt>p</tt> and <tt>q</tt> are in the same
     *    component, and <tt>false</tt> otherwise
     * @throws java.lang.IndexOutOfBoundsException unless both 0 <= p < N and 0 <= q < N
     */
    public boolean connected(int p, int q) {
        return find(p) == find(q);
    }

  
    /**
     * Merges the component containing site<tt>p</tt> with the component
     * containing site <tt>q</tt>.
     * @param p the integer representing one site
     * @param q the integer representing the other site
     * @throws java.lang.IndexOutOfBoundsException unless both 0 <= p < N and 0 <= q < N
     */
    public void union(int p, int q) {
        int rootP = find(p);
        int rootQ = find(q);
        if (rootP == rootQ) return;
        id[rootP] = rootQ; 
        count--;
    }

    /**
     * Reads in a sequence of pairs of integers (between 0 and N-1) from standard input, 
     * where each integer represents some object;
     * if the objects are in different components, merge the two components
     * and print the pair to standard output.
     */
    public static void main(String[] args) {
        int N = StdIn.readInt();
        QuickUnionUF uf = new QuickUnionUF(N);
        while (!StdIn.isEmpty()) {
            int p = StdIn.readInt();
            int q = StdIn.readInt();
            if (uf.connected(p, q)) continue;
            uf.union(p, q);
            StdOut.println(p + " " + q);
        }
        StdOut.println(uf.count() + " components");
    }


}

Quick-Union的缺点是:在极端情况下,树会生长成笔直的直线。可用Weighted Quick-Union算法改进。
Weighted Quick-Union在原来的基础上,保存树的重量,两棵树合并时,重量小的树做为重量大的树的一棵子树。如上图中,根为9的树,重量为4,根为6的树重量为2,当这两棵树合并时,根为6的树作为根为9的树的子树。要实现该功能,需要引入数组int sz[N],其中,sz[i]保存以i为根节点的树重量。在union方法中,需要额外添加如下代码:
if   (sz[rootP] < sz[rootQ]) { id[rootP] = rootQ; sz[rootQ] += sz[rootP]; }
else                         { id[rootQ] = rootP; sz[rootP] += sz[rootQ]; }

Weighted Quick-Union算法具体实现如下:
/****************************************************************************
 *  Compilation:  javac WeightedQuickUnionUF.java
 *  Execution:  java WeightedQuickUnionUF < input.txt
 *  Dependencies: StdIn.java StdOut.java
 *
 *  Weighted quick-union (without path compression).
 *
 ****************************************************************************/

/**
 *  The <tt>WeightedQuickUnionUF</tt> class represents a union-find data structure.
 *  It supports the <em>union</em> and <em>find</em> operations, along with
 *  methods for determinig whether two objects are in the same component
 *  and the total number of components.
 *  <p>
 *  This implementation uses weighted quick union by size (without path compression).
 *  Initializing a data structure with <em>N</em> objects takes linear time.
 *  Afterwards, <em>union</em>, <em>find</em>, and <em>connected</em> take
 *  logarithmic time (in the worst case) and <em>count</em> takes constant
 *  time.
 *  <p>
 *  For additional documentation, see <a href="http://algs4.cs.princeton.edu/15uf">Section 1.5</a> of
 *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.
 *     
 *  @author Robert Sedgewick
 *  @author Kevin Wayne
 */
public class WeightedQuickUnionUF {
    private int[] id;    // id[i] = parent of i
    private int[] sz;    // sz[i] = number of objects in subtree rooted at i
    private int count;   // number of components

    /**
     * Initializes an empty union-find data structure with N isolated components 0 through N-1.
     * @throws java.lang.IllegalArgumentException if N < 0
     * @param N the number of objects
     */
    public WeightedQuickUnionUF(int N) {
        count = N;
        id = new int[N];
        sz = new int[N];
        for (int i = 0; i < N; i++) {
            id[i] = i;
            sz[i] = 1;
        }
    }

    /**
     * Returns the number of components.
     * @return the number of components (between 1 and N)
     */
    public int count() {
        return count;
    }

    /**
     * Returns the component identifier for the component containing site <tt>p</tt>.
     * @param p the integer representing one site
     * @return the component identifier for the component containing site <tt>p</tt>
     * @throws java.lang.IndexOutOfBoundsException unless 0 <= p < N
     */
    public int find(int p) {
        while (p != id[p])
            p = id[p];
        return p;
    }

    /**
     * Are the two sites <tt>p</tt> and <tt>q</tt> in the same component?
     * @param p the integer representing one site
     * @param q the integer representing the other site
     * @return <tt>true</tt> if the two sites <tt>p</tt> and <tt>q</tt>
     *    are in the same component, and <tt>false</tt> otherwise
     * @throws java.lang.IndexOutOfBoundsException unless both 0 <= p < N and 0 <= q < N
     */
    public boolean connected(int p, int q) {
        return find(p) == find(q);
    }

  
    /**
     * Merges the component containing site<tt>p</tt> with the component
     * containing site <tt>q</tt>.
     * @param p the integer representing one site
     * @param q the integer representing the other site
     * @throws java.lang.IndexOutOfBoundsException unless both 0 <= p < N and 0 <= q < N
     */
    public void union(int p, int q) {
        int rootP = find(p);
        int rootQ = find(q);
        if (rootP == rootQ) return;

        // make smaller root point to larger one
        if   (sz[rootP] < sz[rootQ]) { id[rootP] = rootQ; sz[rootQ] += sz[rootP]; }
        else                         { id[rootQ] = rootP; sz[rootP] += sz[rootQ]; }
        count--;
    }


    /**
     * Reads in a sequence of pairs of integers (between 0 and N-1) from standard input, 
     * where each integer represents some object;
     * if the objects are in different components, merge the two components
     * and print the pair to standard output.
     */
    public static void main(String[] args) {
        int N = StdIn.readInt();
        WeightedQuickUnionUF uf = new WeightedQuickUnionUF(N);
        while (!StdIn.isEmpty()) {
            int p = StdIn.readInt();
            int q = StdIn.readInt();
            if (uf.connected(p, q)) continue;
            uf.union(p, q);
            StdOut.println(p + " " + q);
        }
        StdOut.println(uf.count() + " components");
    }

}

Weighted Quick-Union在极端情况下,union方法的时间复杂度需要O(lgN),是否能对该算法进一步优化呢?答案是肯定的——使用路径压缩算法(Weighted Quick-Union with Path Compression)

如上图所示,在寻找9的根节点过程中,依次访问了节点6、3、1、0。借用访问过程,只需要在root方法中加入一行,即可以把节点跳二级提升。
private int root(int i)
{
   while (i != id[i])
   {
        id[i] = id[id[i]];//only one extra line of code
	i = id[i]; 
   }
   return i; 

}



上例中,经过一次查找9的根节点,可以把9指向3,把3指向0,从而缩小了树的高度。使用Path Compression优化后,Union时间复杂度提高到lg*N。(lg*N表示将N变为1需要lg迭代次数)



综上所述,Quick-Union算法及其改进算法的时间复杂度如下:

algorithmworst-case time
quick-unionM N
weighted QUN + M log N
weighted QU + path compressionN + M lg* N

如何利用VS2017创建一个简单的窗口 #如何利用VS2017创建一个简单的窗口 1、新建->Windows桌面向导 2、应用程序类型->桌面应用程序,点击确定 3、点击调试->开始调试 可建立如下图的窗口 4、可以在生成的项目文件的中找到windows17_2的应用程序,打开界面如下: 注:新建空白项目也可以,注意在解决方案资源器中添加.cpp文件,如源.cpp文件,下载代码见博文 ... 阅读详情

相关推荐

Jetson AGX Orin 新手避坑:解决‘找不到nvidia-jetpack包’的完整修复指南

本文详细介绍了Jetson AGX Orin设备在安装JetPack开发套件时遇到的'nvidia-jetpack包缺失'问题的完整解决方案。通过分析问题根源、提供分步修复指南以及系统优化建议,帮助开发者快速解决这一常见问题,充分发挥Jetson AGX Orin的边缘计算性能。

weixin_42520909的博客 460

连通分量(quick-union)

连通域问题的抽象表述是存在N个节点和M条边,被边直接或间接相连的所有节点共同形成一个域,称为连通域。在进行有限次的连接后,需要快速求出连通域的个数,或者判断任意两个节点的连通性。连通域的个数也称为连通分量,该算法也被称为Union-Find。

陈戏猿 8014

R语言 | 关联规则

关联规则(AssociationRules)是无监督的机器学习方法,用于知识发现,而非预测。 关联规则的学习器(learner)无需事先对训练数据进行打标签,因为无监督学习没有训练这个步骤。缺点是很难对关联规则学习器进行模型评估,一般都可以通过肉眼观测结果是否合理。 关联规则主要用来发现Pattern,最经典的应用是购物篮分析,当然其他类似于购物篮交易数据的案例也可以应用关联规则进行模式发现。

I think so I am 10万+

并查集 -- QuickUnion(Java语言)

需求分析 假设场景: 有n个村庄,有些村庄之间有连接的路,有些村庄并没有连接的路。 设计一个数据结构,能快速实现以下两个操作: (1)查询任意两个村庄之间是否有连接的路。 (2)连接任意两个村庄。 平衡二叉树、集合、数组、链表也能实现上述需求,但这些工具能实现的功能更多,与专注于实现上述特定需求的并查集来说效率并不理想。 并查集的实现有QuickFind、QuickUnion两种方式,本文采取后者实现。QuickUnion - 底层是数组,逻辑层面是树。 首先初始化每个节点的父节点为自己 --初始化每个“

gsd的博客 668

手把手教你为STM32设备生成自定义MAC地址(基于芯片ID的5种算法对比)

本文详细介绍了基于STM32芯片ID生成自定义MAC地址的5种算法,包括直接截取、异或折叠、CRC32哈希、自定义混合运算及SHA-256摘要。通过对比分析各算法的计算复杂度、唯一性及适用场景,帮助嵌入式开发者根据项目规模与资源,选择最合适的方案,确保设备MAC地址的唯一性与合规性。

weixin_29170327的博客 526

AI影像组学在结直肠癌诊疗中的应用:从特征提取到临床决策

影像组学通过高通量计算从医学影像中提取定量特征,揭示肿瘤内部的微观生物学行为,这些特征反映了纹理异质性、形状不规则度等影像表型。其核心原理在于将图像数据转化为可分析的数字特征,结合机器学习算法进行模式识别,从而实现对疾病状态的精准预测。这一技术的价值在于能够无创、定量地评估肿瘤特性,为精准医疗提供关键支持。在临床实践中,AI驱动的影像组学模型广泛应用于结直肠癌的诊疗全链条,包括肿瘤良恶性鉴别、基因突变预测、治疗反应评估和预后分析等场景。通过整合影像组学特征与临床数据,可以构建预测模型,辅助医生进行更准确的诊

weixin_28295799的博客 409

Quick-Union算法

前言 在上一节博客上已经介绍了Quick-Find算法,但是呢,Quick-Find算法太low了,运行慢,要是拿着它去找13亿人的关系链,那怕是电脑的风扇不太够用啊。所以我们这次学习它的升级版Quick-Union。 Quick-Union算法 回忆Quick-Find中union函数,就像是暴力强算,遍历所有数字的ID,然后把有着相同ID的数全部改掉,现在我们来引入“树”的概念来...

qq_39747794的博客 2598

生物信息学避坑指南:Scissor算法参数alpha和cutoff的黄金设置法则

本文深入解析了生物信息学中Scissor算法的关键参数alpha和cutoff的黄金设置法则,帮助研究者有效整合bulk RNA与单细胞数据,识别单细胞亚群。通过实战验证的调参策略,避开常见陷阱,获得可靠的生物学发现,特别适用于肿瘤异质性研究和免疫细胞分型等场景。

weixin_33734785的博客 450

Quick Union

Quick Union quick union就是快速连接 和quick find相同,也是构建一个数组id[],不过存的值换一种理解: 每个数组内的元素看做一个结点,结点内的值即id[i]看做i的前驱结点. 初始化时将每个元素的前驱结点赋值为其下标,即id[]={0,1,2,3...,N-1}. 认为前驱结点和本身相同的结点为根结点,所以以上初始化就是将每个元素的根节点初始化...

dengjiangcw63945的博客 202

SAP 行业扫盲系列之一:SAP 从业者的分类

本文简单介绍了 SAP 从业者的分类,限于笔者狭隘的视角,可能存在遗漏或者不恰当的地方,希望大家在评论区指出。 那些在知乎咨询上向我提问关于进入 SAP 行业建议的朋友们,也请大家提问时注明自己想具体从事 SAP 行业哪一类的工作,这样才能得到更让你们满意的回复。感谢阅读。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 1589

【AI智能体】基于Coze 制作高质量PPT实战操作详解

基于Coze 制作高质量PPT实战操作详解

congge 6099

QuickUnion优化及Huffman树

指的是从根结点到该结点之间的路径长度与该结点的权的乘积。树的带权路径长度为树中所有叶子结点的带权路径长度之和。例如在一棵树中,规定根结点所在层数为1层,那么从根结点到第i层结点的路径长度为从根结点到结点 c 的路径长度为 3。当我们进行根节点的查找,可以将每个经过的节点放入一个栈,找到根节点后再把栈的所有节点一一出栈并把这些节点的父节点改为根节点。由于每次合并、查找都需要得到元素的根节点,而当我们的树路径过长效率不高,因此我们可以将每个元素的父节点都指向根节点。例如,结点al17,结点b 的权为5。

2503_92099422的博客 277

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

并查集(Union-Find Algorithm),看这一篇就够了

动态连接(Dynamic connectivity)的问题 所谓的动态连接问题是指在一组可能相互连接也可能相互没有连接的对象中,判断给定的两个对象是否联通的一类问题。这类问题可以有如下抽象: 有一组构成不相交集合的对象 union: 联通两个对象 find: 返回两个对象之间是否存在一条联通的通路 ˇ 在使用union-find处理动态连接的问题时,我们一般将这一组对象抽象...

正西风落叶下长安 3万+

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

Quick-Union

Quick-union solution to connectivity problem #include using namespace std; const int N = 100; int main() { int i, j; int p, q, id[N]; for (i=0; i<N; i++) { id[i] = i; } wh

lungfei 749

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

[Algorithms]union-find连通性算法/quick-find/quick-union/加权quick-union

union-find连通性算法 通俗讲就是寻找两点之间的连通,调用connected():如果某一对整数中两个触点已经连通,就继续处理下一对,如果不连通,则调用union()并打印这对触点。 模板 package union_find; import edu.princeton.cs.algs4.StdIn; import edu.princeton.cs.algs4.St...

对未知的一切抱有热忱 537

Algorithm Part I:Union-Find

1.动态联通性问题描述:        有N个元素,开始时我们让每一个元素肚子构成一个集合。然后按一定的顺序将属于同一组中的元素合并,构成新的集合。其间要反复查询某个元素在哪个集合中。如下所示: 解决办法: (1)Quick-Find 声明一个长度为N的数组id,数组中元素的值代表它所属组的编号。将数组中的元素初始化为每个元素的索引值,这样就表示开始时每个元素各自构成一个独立的集合

yao_hust_iAC的专栏 5313

Algorithm第四版算法 C++实现(一)——union-find算法(并查集)

union-find是用来解决动态连通性问题的算法,可以返回对应的图的连通分量数 这是书中给出的对应API qucik-find main.cpp #include <iostream> #include "head.h" using namespace std; int main() { int n; cin >> n; union_find uf(n); uf.uni(); return 0; } /* test data 10 4 3 3 8 6 5 9 4 2

Charlesix59的博客 717

并查集 Union-Find

并查集 Union-Find 基本结构 public class UF { private int count; private int[] id; public UF(int n) { count = n; id = new int[n]; for (int i = 0; i < n; i++) { ...

Mapoos 303

并查集(Union-Find)算法介绍 Algorithm 4th Part 1

 本文主要介绍解决动态连通性一类问题的一种算法,使用到了一种叫做并查集的数据结构,称为Union-Find。 更多的信息可以参考Algorithms 一书的Section 1.5,实际上本文也就是基于它的一篇读后感吧。 原文中更多的是给出一些结论,我尝试给出一些思路上的过程,即为什么要使用这个方法,而不是别的什么方法。我觉得这个可能更加有意义一些,相比于记下一些结论。

LeoNard'S Blog 549

Algorithm - Union Find

public class UnionFind { static class QuickFindUF { // id[i] is int[] id; /** * Initialize data structure */ QuickFindUF(int N) { id = new int[N]; for (int i = 0; i < N; i++) { id[i] = i; } } /** * p and q are co...

u011183517的专栏 248

Algorithm, Part I Princeton University 公开课第一周 Union-Find算法

Union-Find with Weighted Union and find path compression 一个使用Union-Find的例子  使用Java语言描述 public class SocialNetwork{ public void main(String[] args){ } public class UnionFind{ pr

sesiria的博客 1007

【Algorithms 4】算法(第4版)学习笔记 01 - 1.5 案例研究:union-find算法

《算法(第4版)》1.5 案例研究:union-find算法

MichelleChung的星球 1362

Coursera-Algorithm Day1 Note

Union-Find ProblemDynamic Connectivity ProblemDescriptionProperities of connectionQuick Find SolutionQuick Union SolutionSolution ImpovementsImprovement 1: weightingImprovement 2: path compressionWeig...

AndrewZ_98的博客 492

COS 126 - Union-Find

Union-Find 文章目录Union-Finddynamic connectivityqucik findquick unionimprovements dynamic connectivity Given a set of N objects.: Union command and find/connected query. it like: connected(0,7) or union(...

yinzhuochao的博客 383

算法(第四版)学习笔记1--第一章--union-find算法

算法第一章-基础-1.5案例研究:union-find算法 问题陈述:动态连通性。给出一个整数集合,然后输入一列整数对,&lt;p,q&gt;代表p和q是连通的,即在一个连通分量重,最后得到这个整数集合的所有连通分量。 三种算法(第四种属理论): 1)quick-find:用一个数组,数组下标代表所有整数,内容是下标整数所在的连通分量标志,选该连通分量里的某一个整数作为标志。这样,每两个不同...

Charles.L的博客 1129

Algorithm第四版笔记-基础

Algorithm第四版笔记-基础 pre.src {background-color: #000000; color: #eaeaea;} pre.src {background-color: #000000; color: #eaeaea;} pre.src {background-color: #000000; color: #eaeaea;} ...

weixin_34384915的博客 243
上一篇: 正则表达式实例
下一篇: Search a 2D Matrix ——Leetcode系列(十八)
Hooting
博客等级 码龄17年 11粉丝 44原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值