--------------------siwuxie095

 
 

 
 

 
 

 
 

 
 

 
 

 
 

 
 

Quick Find

 
 

 
 

这里介绍并查集的一种实现思路:Quick Find

 
 

 
 

 
 

对于一组数据,并查集主要支持两个操作:

 
 

(1)union( p , q ),即 并,将 p 和 q 两个元素合并在一起,也就是所谓的连接

 
 

(2)find( p ),即 查,查找 p 元素具体在哪个集合中

 
 

 
 

 
 

有了这两个操作,使用并查集也可以轻易地回答这样一个问题:

 
 

isConnected( p , q ),传入 p 和 q 两个元素,判断两个元素是否相连接

 
 

 
 

 
 

并查集的基本数据表示

 
 

对于如上需求,最简单的数据表示方式就是数组,其中:数组的索引

用来表示元素

 
 

如果有 0-9,共 10 个元素,这些元素之间连接关系的表示方法如下:

 
 

「即
给每一个元素都赋上一个值」

 
 

(1)

 
 

 
 

 
 

0-4 对应的值都是 0,而 5-9 对应的值都是 1。表示 0-4 这 5 个

元素之间是互相连接的,而 5-9 这 5 个元素之间是互相连接的

 
 

 
 

 
 

(2)

 
 

 
 

 
 

0、2、4、6、8 对应的值都是 0,而 1、3、5、7、9 对应的值都

是 1。表示 5 个偶数和 5 个奇数是分别互相连接的

 
 

 
 

 
 

不妨给这个数组起一个名字,叫做 id,即 所有连接在一起的元素,

它们都具有相同的
id

 
 

 
 

 
 

 
 

 
 

程序:Quick Find 的实现

 
 

UnionFind.h:

 
 

#ifndef UNIONFIND_H

#define UNIONFIND_H

 
 

#include <iostream>

#include <cassert>

using namespace std;

 
 

 
 

 
 

//并查集:Quick Find

namespace UF

{

 
 

class UnionFind

{

 
 

private:

int *id;

int count;

 
 

public:

UnionFind(int count)

{

this->count = count;

id = new
int[count];

//在初始情况下,并查集里的元素,两两之间互不连接

for (int i = 0; i < count; i++)

{

id[i] = i;

}

}

 
 

 
 

~UnionFind()

{

delete []id;

}

 
 

 
 

//找到每一个元素所集合的id:直接访问id相应的值即可

//称这种实现为 Quick Find,也就是Find操作非常快,

//只需要使用O(1)的时间复杂度就够了

int find(int p)

{

assert(p >= 0 && p < count);

return id[p];

}

 
 

 
 

//回答两个元素是否相互连接的问题:id相同则相互连接

bool isConnected(int p, int q)

{

return find(p) == find(q);

}

 
 

 
 

//Quick Find下的Union操作的时间复杂度 O(n)

//(因为union在C++中是关键字,所以不能把函

//数名起成union)

void unionElements(int p, int q)

{

 
 

int pID = find(p);

int qID = find(q);

 
 

if (pID == qID)

{

return;

}

 
 

//Union操作是将两个元素所在集合全部并在一起,而不是只将 p 元素

//并到 q 元素所在集合,或只将 q 元素并到 p 元素所在集合

//

//这样,本来两个元素所在集合的所有元素,两两之间就互相连接了

for (int i = 0; i < count; i++)

{

//或者反向亦可

if (id[i] == pID)

{

id[i] = qID;

}

}

 
 

}

};

}

 
 

 
 

#endif

 
 

 
 

 
 

UnionFindTestHelper.h:

 
 

#ifndef UNIONFINDTESTHELPER_H

#define UNIONFINDTESTHELPER_H

 
 

#include
"UnionFind.h"

#include <iostream>

#include <ctime>

using namespace std;

 
 

 
 

 
 

namespace UnionFindTestHelper

{

 
 

void testUF(int n)

{

//设置随机种子

srand(time(NULL));

UF::UnionFind uf = UF::UnionFind(n);

 
 

time_t startTime = clock();

 
 

//先进行n次的并,即 Union 操作

for (int i = 0; i < n; i++)

{

int a = rand() % n;

int b = rand() % n;

uf.unionElements(a, b);

}

 
 

//再进行n次的查,即 Find 操作

for (int i = 0; i < n; i++)

{

int a = rand() % n;

int b = rand() % n;

uf.isConnected(a, b);

}

 
 

time_t endTime = clock();

 
 

//打印2*n个操作耗费的时间

cout << "UF, " << 2 * n << " ops, " << double(endTime - startTime) / CLOCKS_PER_SEC

<< " s" << endl;

}

}

 
 

 
 

//由于单个Union操作的时间复杂度是O(n)级别的,所以执行n次Union操作,

//时间复杂度就是O(n^2)级别的

//

//而在查看是否连接isConnected()的复杂度是O(1),执行n个操作,就是O(n)

//

//不过整体上,此次测试的复杂度是O(n^2)级别的

//

//即 Quick Find,它查找(Find)的速度非常快,可是在执行并(Union)这个

//操作的时候,效率却不尽人意

 
 

#endif

 
 

 
 

 
 

main.cpp:

 
 

#include
"UnionFindTestHelper.h"

#include <iostream>

using namespace std;

 
 

 
 

 
 

int main()

{

//规模是十万

int n = 100000;

 
 

UnionFindTestHelper::testUF(n);

 
 

system("pause");

return
0;

}

 
 

 
 

运行一览:

 
 

 
 

 
 

 
 

 
 

 
 

 
 

 
 

 
 

 
 

 
 

【made by siwuxie095】

Quick Find的更多相关文章

  1. [算法]——快速排序(Quick Sort)

    顾名思义,快速排序(quick sort)速度十分快,时间复杂度为O(nlogn).虽然从此角度讲,也有很多排序算法如归并排序.堆排序甚至希尔排序等,都能达到如此快速,但是快速排序使用更加广泛,以至于 ...

  2. Quick Cocos (2.2.5plus)CoinFlip解析(MenuScene display AdBar二次封装)

    转载自:http://cn.cocos2d-x.org/tutorial/show?id=1621 从Samples中找到CoinFlip文件夹,复制其中的 res 和 script 文件夹覆盖新建工 ...

  3. 《Qt Quick 4小时入门》学习笔记4

    http://edu.csdn.net/course/detail/1042/14806?auto_start=1 Qt Quick 4小时入门 第七章:处理鼠标与键盘事件 1.处理鼠标事件 鼠标信号 ...

  4. 《Qt Quick 4小时入门》学习笔记3

    http://edu.csdn.net/course/detail/1042/14807?auto_start=1 Qt Quick 4小时入门 第八章:Qt Quick中的锚(anchors)布局 ...

  5. 《Qt Quick 4小时入门》学习笔记2

    http://edu.csdn.net/course/detail/1042/14805?auto_start=1   Qt Quick 4小时入门 第五章:Qt Quick基本界面元素介绍   1. ...

  6. spring in action 4th --- quick start

    读spring in action. 环境搭建 quick-start依赖注入 面向切面 1.环境搭建 jdk1.8 gradle 2.12 Intelij idea 2016.2.1 1.1创建一个 ...

  7. A Quick Introduction to Linux Policy Routing

    A Quick Introduction to Linux Policy Routing 29 May 2013 In this post, I’m going to introduce you to ...

  8. Quick Apps for Sharepoint小型BI解决方案

    Quick Apps for Sharepoint介绍 Quick Apps for Sharepoint前身是Quest Webpart ,由企业软件开发商QuestSoftware开发,Quest ...

  9. Sharepoint + Office Infopart + Quick Apps for Sharepoint搭建无纸化工作平台

    项目背景: 某大型外企各分部通过互联网专线统一域环境,Exchange邮件系统,Sharepoint平台及依赖环境已经购买并搭建起来,Dell Quick app for Sharepoint已购卖并 ...

  10. cocos2d-x quick 学习 二 Hello world

    总算找到问题了. 这几天一直在招问题没有找到原因. 为什么按照文档就不能建立新的项目.  不能建立自己的 hello world 我之前下载的源码文件 quick-cocos2d-x-2.2.5   ...

随机推荐

  1. (效果一)js实现上拉加载

    实现思路:获取滚动元素的高度,滚动条距离顶部的距离,滚动条的高度, 算式:可视窗口的高度 + 滚动条距离顶部的距离 == 滚动条的高度就说明到底部. HTML <!doctype html> ...

  2. python学习之面向对象(下)

    该篇主要是针对面向对象的细讲,包括类的多重继承,方法的重写,析构函数,回收机制进行讲解 #该类主要是讲述python面象对象的一些特征,包括继承,方法的重写,多态,垃圾回收 class person( ...

  3. 21天学通C++_Day3_Part3

    控制程序流程 0.switch...case...语句中省略了break? break让程序能够退出switch结构,如果没有将继续评估后面的case语句 1.如何退出无限循环? 使用break退出当 ...

  4. HDU - 6183:Color it (线段树&动态开点||CDQ分治)

    Do you like painting? Little D doesn't like painting, especially messy color paintings. Now Little B ...

  5. 【4】JDK和CGLIB生成动态代理类的区别

    当一个对象(客户端)不能或者不想直接引用另一个对象(目标对象),这时可以应用代理模式在这两者之间构建一个桥梁--代理对象. 按照代理对象的创建时期不同,可以分为两种: 静态代理:事先写好代理对象类,在 ...

  6. FastAdmin 导出 Excel 相关资料收集 (2018-08-14)

    FastAdmin 导出 Excel 相关资料收集 导出 Excel 文件时身份证号变成科学计数法怎么办? https://forum.fastadmin.net/thread/1346 姊妹篇 Fa ...

  7. bzoj 1499 [NOI2005]瑰丽华尔兹——单调队列优化dp

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1499 简单的单调队列优化dp.(然而当时却WA得不行.今天总算填了坑) 注意滚动数组赋初值应 ...

  8. Jython引用Java类

    Ubuntu下如下指令安装Jython:$ sudo apt-get install jython下面的指令用于查看Jython版本:$ jython --version下面的代码是一个简单的Java ...

  9. linux下用户和组相关的文件及相关管理命令

    1.用户信息文件  /etc/passwd 示例root:x:0:0:root:/root:/bin/bashbin:x:1:1:bin:/bin:/sbin/nologindaemon:x:2:2: ...

  10. Oracle LSNRCTL------监听器的启动和关闭

    对于DBA来说,启动和关闭oracle监听器是很基础的任务,但是Linux系统管理员或者程序员有时也需要在开发数据库中做一些基本的DBA操作,因此了解一些基本的管理操作对他们来说很重要. 本文将讨论用 ...