Quick Find
--------------------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 //在初始情况下,并查集里的元素,两两之间互不连接 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 #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 #include <iostream> using namespace std; int main() { //规模是十万 int n = 100000; UnionFindTestHelper::testUF(n); system("pause"); return } |
运行一览:
【made by siwuxie095】
Quick Find的更多相关文章
- [算法]——快速排序(Quick Sort)
顾名思义,快速排序(quick sort)速度十分快,时间复杂度为O(nlogn).虽然从此角度讲,也有很多排序算法如归并排序.堆排序甚至希尔排序等,都能达到如此快速,但是快速排序使用更加广泛,以至于 ...
- Quick Cocos (2.2.5plus)CoinFlip解析(MenuScene display AdBar二次封装)
转载自:http://cn.cocos2d-x.org/tutorial/show?id=1621 从Samples中找到CoinFlip文件夹,复制其中的 res 和 script 文件夹覆盖新建工 ...
- 《Qt Quick 4小时入门》学习笔记4
http://edu.csdn.net/course/detail/1042/14806?auto_start=1 Qt Quick 4小时入门 第七章:处理鼠标与键盘事件 1.处理鼠标事件 鼠标信号 ...
- 《Qt Quick 4小时入门》学习笔记3
http://edu.csdn.net/course/detail/1042/14807?auto_start=1 Qt Quick 4小时入门 第八章:Qt Quick中的锚(anchors)布局 ...
- 《Qt Quick 4小时入门》学习笔记2
http://edu.csdn.net/course/detail/1042/14805?auto_start=1 Qt Quick 4小时入门 第五章:Qt Quick基本界面元素介绍 1. ...
- spring in action 4th --- quick start
读spring in action. 环境搭建 quick-start依赖注入 面向切面 1.环境搭建 jdk1.8 gradle 2.12 Intelij idea 2016.2.1 1.1创建一个 ...
- 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 ...
- Quick Apps for Sharepoint小型BI解决方案
Quick Apps for Sharepoint介绍 Quick Apps for Sharepoint前身是Quest Webpart ,由企业软件开发商QuestSoftware开发,Quest ...
- Sharepoint + Office Infopart + Quick Apps for Sharepoint搭建无纸化工作平台
项目背景: 某大型外企各分部通过互联网专线统一域环境,Exchange邮件系统,Sharepoint平台及依赖环境已经购买并搭建起来,Dell Quick app for Sharepoint已购卖并 ...
- cocos2d-x quick 学习 二 Hello world
总算找到问题了. 这几天一直在招问题没有找到原因. 为什么按照文档就不能建立新的项目. 不能建立自己的 hello world 我之前下载的源码文件 quick-cocos2d-x-2.2.5 ...
随机推荐
- (三十七)js改变this指向的方法
最近又遇到了JacvaScript中的call()方法和apply()方法,而在某些时候这两个方法还确实是十分重要的,那么就让我总结这两个方法的使用和区别吧. 1.改变函数内部的this指向的三种方法 ...
- timer用作timestamp及其他
niosii中使用时间戳是很有用的,可以查看代码的执行时间是多少,在使用timestamp的过程中遇到一些问题现在做一下记录. 1.硬件部分构建软核没什么,就加一个timer就行了,加完之后自动获得基 ...
- LG3195 [HNOI2008]玩具装箱TOY
题意 P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中.P教授有编号为\(1\cdots N\) ...
- springboot 自定义属性
前言 spring boot使用application.properties默认了很多配置.但需要自己添加一些配置的时候,我们如何添加呢 1.添加自定义属性 在src/main/resources/a ...
- 最全的Javascript编码规范(推荐)
1.嵌入规则 Javascript程序应该尽量放在.js的文件中,需要调用的时候在页面中以<script src="filename.js">的形式包含进来.Javas ...
- ASP.NET Cache缓存的使用
ASP.NET Cache是提升系统性能的重要方法,它使用了“最近使用”原则(a least-recently-used algorithm).在数据库访问中经常会用到Cache保存数据库数据. 1. ...
- QtAV的编译方法
1--编译准备 QtAV的安装编译总指导说明:https://github.com/wang-bin/QtAV/wiki/Build-QtAV QtAV的源代码:https://github.com/ ...
- php 两种或的区别 or ||
php 两种或的区别 or || 实验代码. <?php $p = 999 or 1; var_dump($p); $q = 999 | 1; var_dump($q);
- Java 虚拟机-垃圾收集算法
本文主要介绍Java虚拟机的垃圾回收算法. 一.概述 二.标记-清除算法 Mark-Sweep.如同名字,该算法分两步: 标记:标记处需要回收的对象 清除:标记完成后统一回收被标记的对象. 缺点: 效 ...
- rbenv配置
git clone https://github.com/rbenv/rbenv.git ~/.rbenv # 用来编译安装 ruby git clone git://github.com/sstep ...