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

Codesys电子凸轮实战:从机械替代到虚轴设计的5个关键步骤 本文详细介绍了Codesys电子凸轮技术在运动控制领域的实战应用,从机械替代到虚轴设计的5个关键步骤。通过电子凸轮技术,操作员可以快速调整切割模式,显著提升产线效率。文章还探讨了虚轴架构、CAM表设计、动态耦合技巧及调试避坑指南,为工业自动化领域提供了实用的解决方案。 阅读详情

相关推荐

CTFShow萌新区全攻略:从密码破解到Web渗透的实战解析

本文为CTFShow萌新区新手提供从密码破解到Web渗透的完整实战攻略。文章深入解析了密码学、隐写术、杂项和Web安全四大核心方向,分享了实用的解题工具、思维方法和绕过技巧,旨在帮助初学者建立系统的安全竞赛解题体系,而不仅仅是提供一份题解(WP)。

weixin_29216957的博客 297

连通分量(quick-union)

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

陈戏猿 8014

[EDA系列]二、Altium Designer异形封装实战:从CAD导入到PCB布局

本文详细介绍了在Altium Designer中实现异形封装的实战流程。通过五步核心操作,将CAD软件中的复杂二维轮廓精准导入并转换为可直接用于PCB布局的智能封装,解决了不规则形状铺铜的难题,特别适用于射频天线、传感器外壳等对机械尺寸有严苛要求的设计场景。

weixin_29194817的博客 142

并查集 -- QuickUnion(Java语言)

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

gsd的博客 668

星光、黑光、全彩夜视摄像头技术解析与实战选型指南

本文深入解析了星光、黑光、全彩与红外等主流夜视摄像头技术的工作原理与核心差异。针对不同监控场景与预算,提供了实战选型指南,帮助用户在安防项目中做出明智决策,实现夜间监控效果最大化。

weixin_29179311的博客 345

[工具使用]黑暗引擎FOFA

黑暗引擎FOFAFOFA(点我进入)逻辑运算符搜索子域名domain搜索指定内容的host全部域名bodycert搜索选定应用的网站搜索指定开放端口的IP搜索指定协议的IP搜索IP或者网段的信息搜索指定CSS/JS网站常用的一些内容其他 FOFA(点我进入) 官网这样描述:FOFA是白帽汇推出的一款网络空间资产搜索引擎。它能够帮助用户迅速进行网络资产匹配、加快后续工作进程。例如进行漏洞影响范围分析、应用分布统计、应用流行度排名统计等。 简单理解就是,一个本土加强版shodan,知道某产品在互联网的部署情况、

网络安全知识分享 3万+

Quick-Union算法

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

qq_39747794的博客 2598

Virtuoso集成HspiceD:打通模拟设计全流程的仿真与PEX实战

本文详细介绍了Virtuoso集成HspiceD在模拟设计全流程中的应用,包括仿真与PEX实战。通过无缝衔接Virtuoso和HspiceD,设计师可以在同一环境中完成从原理图设计到PEX后仿真的全流程,大幅提升工作效率。文章还提供了仿真环境配置、前仿真关键设置、PEX全流程详解以及性能调优等实用技巧。

weixin_29271263的博客 96

Quick Union

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

dengjiangcw63945的博客 202

Android Framework AudioFlinge 面试题及参考答案

请解释什么是 AudioFlinger? AudioFlinger 是 Android 音频系统中的一个关键服务。它位于 Android 系统的中间层,是连接上层应用和底层音频硬件驱动的重要桥梁。从功能角度来讲,它主要负责音频数据的混合(Mix)以及输出(Output)。 当多个应用程序同时播放音频时,比如一个音乐播放器在播放歌曲,同时手机的闹铃响起,AudioFlinger 就会发挥它的混合功能。它会把这些不同来源的音频数据按照一定的规则和算法混合在一起。这种混合并不是简单的相加,而是要考

大模型大数据攻城狮的专栏 1576

多模型动态路由(Fusion):从“算力霸权”到“架构分权”的工程范式转型

多模型动态路由(Multi-Model Dynamic Routing)是指在多个大语言模型之间,根据请求特征、资源约束和业务目标,动态选择最优模型或模型组合的技术范式。传统网关擅长管理请求流量,但不理解“任务类型”。而AI路由层需要对每个请求进行语义理解、能力匹配和成本评估。从“算力霸权”到“架构分权”,这不是技术的线性演进,而是工程范式的根本转型。过去三年,开发者的核心能力是“选对模型”——在GPT、Claude、Gemini之间做出正确选择。

ZDQ58818的博客 73

QuickUnion优化及Huffman树

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

2503_92099422的博客 277

STM32入门教程:智能储物柜控制

在这个例子中,我们将使用一个4x4的储物柜,共有16个储物格。我们了解了硬件准备、储物柜电路设计、STM32的基本配置、储物柜控制代码的编写以及测试和调试等方面的知识。根据我们的电路设计,我们需要将一些引脚配置为输出,并将其他引脚配置为输入。在本教程中,我们将使用STM32微控制器来实现一个基本的智能储物柜控制系统。在主函数中,我们将不断循环读取传感器数据,并根据数据的变化来控制储物柜的开关和显示相关信息。这个函数将读取人体感应传感器、温湿度传感器和光照传感器的数据,并将数据存储到相应的变量中。

m0_75244442的博客 658

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

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

正西风落叶下长安 3万+

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

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

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

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
上一篇: 正则表达式实例
下一篇: 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、付费专栏及课程。

余额充值