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

基于YOLOv11的工业零件表面缺陷检测系统:从原理到实现 工业质量控制是制造业的核心环节,表面缺陷检测作为其中重要组成部分,直接关系到产品质量和企业效益。本文详细介绍了一种基于YOLOv11深度学习算法的工业零件表面缺陷检测系统,包含完整的算法原理分析、数据集构建方法、模型训练策略以及用户界面设计。通过大量实验验证,该系统能够高效准确地检测零件表面的划痕、凹陷、锈蚀等多种缺陷,检测精度达到96.2%,满足工业实时检测需求。本文还提供了完整的代码实现和详细的技术文档,为相关领域的研究者和工程师提供参考。关键词:表面缺陷检测;YOLOv11;深度学习;工业视觉; 阅读详情

相关推荐

PPPoE上网配置不求人:华为路由器命令行操作指南(2023最新版)

本文提供2023年最新的华为路由器PPPoE上网配置命令行操作指南。通过详细的步骤讲解,从连接设备、创建拨号接口、绑定PPPoE客户端到配置内网与NAT,手把手教你完成配置,并附有验证排错方法,助你轻松实现稳定上网。

s4t5u6v的博客 679

连通分量(quick-union)

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

陈戏猿 8014

Modbus4J vs EasyModbus4J:哪个Java库更适合你的工业项目?

本文深入对比了Java领域两大Modbus通信库Modbus4J与EasyModbus4J。Modbus4J设计稳健、类型安全,适合复杂业务集成;EasyModbus4J基于Netty,在高并发场景下性能更优。文章从架构、性能、API及生产环境多维度分析,为工业物联网项目选型提供决策依据。

weixin_28475533的博客 310

并查集 -- QuickUnion(Java语言)

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

gsd的博客 668

opencv实现“找茬”

// 111.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include #include #include using namespace std; #define CVX_RED CV_RGB(0xff,0x00,0x00) #define CVX_BLUE CV_RGB(0x00,0x00,0xff)//定义宏,轮廓边框颜色 in

yanHa007的专栏 2094

MaxEnt物种分布预测中的常见误区与优化技巧:如何提高模型准确率

本文深入探讨了MaxEnt物种分布预测模型从基础应用到精准预测的进阶实践。针对模型准确率提升,文章系统分析了环境变量筛选、模型参数调优、结果批判性解读等核心环节的常见误区,并提供了基于生态位模型原理的深度优化技巧,帮助研究者产出更可靠、可解释的预测结果。

weixin_29219539的博客 594

Quick-Union算法

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

qq_39747794的博客 2598

银河麒麟编译libjpeg库并配置qt环境

银河麒麟下编译libjpeg库并配置qt环境验证

小米的修行之路 1011

Quick Union

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

dengjiangcw63945的博客 202

YOLOv8自定义训练:车牌识别全流程(从标注到推理,附可视化代码)

车牌检测全流程实践指南 摘要:本文详细介绍了基于YOLOv8的车牌检测完整实现方案。针对车牌检测中的三大难点(小目标、多角度、光照变化),提供了从数据准备到模型部署的全流程解决方案。重点包括:1)数据采集与标注规范;2)针对小目标的YOLOv8模型优化配置;3)K-means锚框聚类方法;4)训练参数调优策略。通过实际验证,该方法可获得95%以上的检测准确率,并附有完整的代码实现和可视化工具,便于开发者快速复现应用。 (字数:149字)

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 849

半导体材料仿真:二维材料仿真_(1).二维材料的基本概念

在半导体材料仿真领域,二维材料因其独特的物理和化学性质而受到广泛关注。二维材料,也称为二维纳米材料,是指在二维空间(通常是平面)上具有原子级厚度的材料。这些材料的厚度通常在几个纳米甚至单个原子层的范围内,使得它们在电子、光学、热学和机械性能上表现出与传统三维材料显著不同的特性。本节将详细介绍二维材料的基本概念,包括它们的分类、结构、性质以及在半导体材料仿真中的应用。

2401_87715305的博客 1545

QuickUnion优化及Huffman树

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

2503_92099422的博客 277

以太网PHY寄存器

并且,值得注意的是,由于目前很多百兆的PHY芯片其MAC接口主流的都是SMII/S3MII,8个端口的接口是相互关联的,一个端口设置Isolate可能会影响其他端口的正常使用,因此在使用中注意不要随意更改bit10的状态。Bit10和bit11的区别是,bit11的配置在强制情况下生效,PHY只能工做与bit11指定的工作模式,而bit10的配置在非强制配置情况下生效,仅仅控制PHY在AN时候的优先级,偏向于Maser或者Slave,但是最终的工作模式看协商的结果,不一定和优先级配置的结果一致。

mangofu的博客 292

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

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

正西风落叶下长安 3万+

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

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

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

[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

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

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、付费专栏及课程。

余额充值