问题描述:

在计算机科学中,并查集是一种树型的数据结构,其保持着用于处理一些不相交集合(Disjoint Sets)的合并及查询问题。有一个联合-查找算法union-find algorithm)定义了两个操作用于此数据结构:

Find:确定元素属于哪一个子集。它可以被用来确定两个元素是否属于同一子集;

Union:将两个子集合并成同一个集合;

实现并查集的关键是实现union-find algorithm, 本文根据常用的四种算法,实现了这个类,具体算法实现请参看维基百科;

制造测试数据集,测试几种方法之间性能的指标;

程序代码:


[cpp] view plaincopy
  1. #ifndef _DISJOINT_SET_H_
  2. #define _DISJOINT_SET_H_
  3. #include <stdlib.h>
  4. #include <stdio.h>
  5. #include <assert.h>
  6. #include <time.h>
  7. #include <math.h>
  8. #include "windows.h"
  9. enum DISJOINTWAY
  10. {
  11. COMMON_WAY,
  12. COMPREE_WAY,
  13. WEIGHT_WAY,
  14. WEIGHT_COMPRESS_WAY
  15. };
  16. /*
  17. * encapsulate the class of disjoint set
  18. *
  19. */
  20. #define MAXDISJOINTSET 0xffffff
  21. class DisjointSet
  22. {
  23. public:
  24. DisjointSet( int maxSize = MAXDISJOINTSET ):m_item(0), m_size(maxSize)
  25. {
  26. m_item = new int[maxSize];
  27. for( int i = 0; i < m_size; i++ )
  28. {
  29. m_item[i] = i;
  30. }
  31. m_path = new int[maxSize];
  32. memset( m_path, 1, sizeof(int)*maxSize );
  33. }
  34. ~DisjointSet()
  35. {
  36. Clear();
  37. }
  38. /*
  39. * find interface
  40. *
  41. */
  42. int Find( DISJOINTWAY way, int input )
  43. {
  44. assert( input <  m_size );
  45. switch( way )
  46. {
  47. case COMMON_WAY:
  48. return ImplFindFirst( input );
  49. case COMPREE_WAY:
  50. return ImplFindSecond( input );
  51. case WEIGHT_WAY:
  52. return ImplFindWeight( input );
  53. case WEIGHT_COMPRESS_WAY:
  54. return ImplFindWeightCompree( input );
  55. default:
  56. return -1;
  57. }
  58. }
  59. /*
  60. * make union
  61. *
  62. */
  63. void Union( DISJOINTWAY way, int first, int second )
  64. {
  65. assert( first < m_size && second < m_size );
  66. switch( way )
  67. {
  68. case COMMON_WAY:
  69. ImplUnionFirst( first, second );
  70. break;
  71. case COMPREE_WAY:
  72. ImplUnionSecond( first, second );
  73. break;
  74. case WEIGHT_WAY:
  75. ImplUnionWeighted( first, second );
  76. break;
  77. case WEIGHT_COMPRESS_WAY:
  78. ImplUnionCompree( first, second );
  79. break;
  80. default:
  81. break;
  82. }
  83. }
  84. /*
  85. *
  86. *
  87. */
  88. void Clear()
  89. {
  90. delete [] m_item;
  91. m_item = 0;
  92. delete [] m_path;
  93. m_path = 0;
  94. m_size = 0;
  95. }
  96. protected:
  97. int ImplFindFirst( int input )
  98. {
  99. assert( input < m_size  );
  100. return m_item[input];
  101. }
  102. int ImplFindSecond( int input )
  103. {
  104. int i = input;
  105. for( ; i != m_item[i]; i = m_item[i] );
  106. return i;
  107. }
  108. int ImplFindWeight( int input )
  109. {
  110. int i = input;
  111. for( ; i != m_item[i]; i = m_item[i] );
  112. return i;
  113. }
  114. int ImplFindWeightCompree( int input )
  115. {
  116. int i = input;
  117. for( ; i != m_item[i]; i = m_item[i] )
  118. m_item[i] = m_item[m_item[i]];
  119. return i;
  120. }
  121. /*
  122. *
  123. *
  124. */
  125. void ImplUnionFirst( int first, int second )
  126. {
  127. int x = m_item[first];
  128. int y = m_item[second];
  129. if( x != y )
  130. {
  131. m_item[first] = y;
  132. }
  133. for( int i = 0; i < m_size; i++ )
  134. {
  135. if( x == m_item[i] )
  136. m_item[i] = y;
  137. }
  138. }
  139. /*
  140. *
  141. *
  142. */
  143. void ImplUnionSecond( int& first, int& second )
  144. {
  145. if( first != second )
  146. {
  147. m_item[first] = second;
  148. }
  149. }
  150. /*
  151. *
  152. *
  153. */
  154. void ImplUnionWeighted( int first, int second )
  155. {
  156. if( first != second )
  157. {
  158. if( m_path[first] < m_path[second] )
  159. {
  160. m_item[first] = second;
  161. m_path[second] += m_path[first];
  162. }
  163. else
  164. {
  165. m_item[second] = first;
  166. m_path[first] += m_path[second];
  167. }
  168. }
  169. }
  170. /*
  171. *
  172. *
  173. */
  174. void ImplUnionCompree( int first, int second )
  175. {
  176. if( first != second )
  177. {
  178. if( m_path[first] < m_path[second] )
  179. {
  180. m_item[first] = second;
  181. m_path[second] += m_path[first];
  182. }
  183. else
  184. {
  185. m_item[second] = first;
  186. m_path[first] += m_path[second];
  187. }
  188. }
  189. }
  190. protected:
  191. int*   m_item;
  192. int    m_size;
  193. int*   m_path;
  194. };
  195. void TestDisjointSetSimple()
  196. {
  197. DisjointSet djoint;
  198. int i = djoint.Find( COMMON_WAY, 1 );
  199. int j = djoint.Find( COMMON_WAY, 3 );
  200. if( i != j )
  201. djoint.Union( COMMON_WAY, 1, 3 );
  202. i = djoint.Find( COMMON_WAY, 2 );
  203. j = djoint.Find( COMMON_WAY, 5 );
  204. if( i != j )
  205. djoint.Union( COMMON_WAY, i, j );
  206. i = djoint.Find( COMMON_WAY, 2 );
  207. j = djoint.Find( COMMON_WAY, 6 );
  208. if( i != j )
  209. djoint.Union( COMMON_WAY, i, j );
  210. i = djoint.Find( COMMON_WAY, 6 );
  211. j = djoint.Find( COMMON_WAY, 7 );
  212. if( i != j )
  213. djoint.Union( COMMON_WAY, i, j );
  214. assert( djoint.Find( COMMON_WAY, 2 ) == djoint.Find( COMMON_WAY, 7 ) );
  215. i = djoint.Find( COMMON_WAY, 1 );
  216. j = djoint.Find( COMMON_WAY, 7 );
  217. if( i != j )
  218. djoint.Union( COMMON_WAY, i, j );
  219. assert( djoint.Find( COMMON_WAY, 3 ) == djoint.Find( COMMON_WAY, 7 ) );
  220. }
  221. void TestDisjointSetComplex( DISJOINTWAY way, const char* str )
  222. {
  223. unsigned long start = GetTickCount();
  224. DisjointSet djoint;
  225. const int len = 1000000;
  226. const int base = 60000;
  227. int halfLen = len / 2;
  228. srand( time(NULL) );
  229. for( int i = 0; i < len; i++ )
  230. {
  231. int first = rand() % base;
  232. int second = rand() % base;
  233. if( i > halfLen )
  234. {
  235. first += base;
  236. second += base;
  237. }
  238. if( first != second )
  239. {
  240. first = djoint.Find( way, first );
  241. second = djoint.Find( way, second );
  242. if( first != second )
  243. djoint.Union( way, first, second );
  244. assert( djoint.Find( way, first ) == djoint.Find( way, second )  );
  245. }
  246. }
  247. unsigned long interval = GetTickCount() - start;
  248. printf(" %s way consume time is %d \n", str, interval );
  249. }
  250. void TestSuiteDisjointSet()
  251. {
  252. TestDisjointSetSimple();
  253. const char* str[] = {"common", "compress", "weight", "weight compress"};
  254. for( int i = WEIGHT_COMPRESS_WAY; i >= 0; i--)
  255. {
  256. TestDisjointSetComplex((DISJOINTWAY)i, str[i] );
  257. }
  258. }
  259. #endif

compile and run in visual studio 2005

下面图片是几种方法运行时间之比较,最直白方法的时间到现在还没输出,所以就没有显示:

并查集类的c++封装,比较union_find algorithm四种实现方法之间的性能差别相关推荐

  1. 美食类短视频如何定位?分享四种类型,选对适合的方向很重要

    美食类短视频如何定位?分享四种类型,选对适合的方向很重要 人人都是"干饭人",所以美食类短视频从来都是不会缺少粉丝的.但是这并不说明做美食类短视频的小伙伴们可以随心所欲的做内容,比 ...

  2. 经典算法-并查集、快速排序、字典序算法、二分搜索、牛顿开方法、求质数(筛选法)、编辑距离、滑动窗口、异或求重、长除法

    目录 ​​​​​​​​​​​​​​ 并查集 快速排序 字典序算法 二分搜索 开根号-牛顿开方法 求质数 编辑距离 滑动窗口 异或求重 长除法 ​​​​​​​ 并查集 并查集用于解决相同元素集合动态连接 ...

  3. 并查集 问题 G: 极品飞车XX星有许多城市,城市之间通过一种奇怪的高速公路SARS(Super Air Roam Structure---超级空中漫游结构)进行交流,每条SARS都对行驶在上面的Fl

    转载于https://www.cnblogs.com/liyinggang/p/5474341.html 负责解说 题目描述 XX星有许多城市,城市之间通过一种奇怪的高速公路SARS(Super Ai ...

  4. 2020.1.30 封装和隐藏(四种访问权限修饰符)、this、JavaBean、继承、方法的重写

    面对对象特征之一:封装和隐藏 Java中通过数据声明为私有的(private),再提供公共的(public)方法:getXxx()和setXxx()实现对属性的操作. 四种访问权限修饰符 在同一个ja ...

  5. 四种Sandcastle方法生成c#.net帮助类帮助文档

    阅读目录(Content) 方法一.Visual Studio新建documentation生成帮助文档 一.下载 二.安装 三.设置 五.生成 方法二.cmd生成帮助文档 方法三.Sandcastl ...

  6. 怎样判断java成员方法,【判断题】在Java中,针对类、成员方法和属性提供了四种访问级别,分别是private、static、protected和public...

    参考答案如下 判断不属于宋徽宗作品的是() 据美国媒体报道,中针美国 CNN电视台5月15日错将总统布什全国电视演讲前的一段失误连连的彩排内容实况播出.画面显示布什彩排时神情极不自信,中针与他在正式演 ...

  7. java成员访问属性,在Java中,针对类、成员方法和属性提供了四种访问级别,分别是private、static、prot...

    You have a file server that runs Windows Server 2008. A user restores a large file by using thePrevi ...

  8. 【模板】并查集 两种路径压缩写法(类模板和函数模板)

    并查集函数模板写法: #include <bits/stdc++.h> using namespace std; typedef long long ll; #define MAX_N 1 ...

  9. POJ 并查集 题目汇总 ——czyuan原创(转)

    继续数据结构的复习,本次的专题是:并查集. 并查集,顾名思义,干的就是"并"和"查"两件事.很多与集合相关的操作都可以用并查集高效的解决. 两个操作代码:    ...

最新文章

  1. oracle exp 乱码 942,Oracle exp/imp字符集相关问题
  2. 【转】二、VTK用于QT的安装
  3. ES6中object对象属性
  4. c语言小游戏代码矿井逃生_如何选择编程语言和逃生教程炼狱
  5. Dom4j下载及使用Dom4j读写XML简介
  6. graphics | 基础绘图系统的拼图方法之三:使用mfrow、mfcol参数和layout函数
  7. asp.net 独立缓存服务器的研究
  8. java 保留小数点后N位数(若干位),几种实现的方式总结
  9. 原 python下DataFrame, Series, ndarray, list, dict, tuple的相互转换
  10. 论文阅读笔记(十)——Acoustic Scene Classification Using Reduced MobileNet Architecture
  11. 简易云在线人事管理系统
  12. 小白速点,计算机的存储规则你知道多少
  13. aria2linux安装教程,Ubuntu 安装下载工具 Aria2
  14. matlab应用最简差分格式,泊松方程有限差分格式的构造以及MATLAB实现.docx
  15. Midjourney之外21款免费的AI Image画图网站集合
  16. DTP加载/ODS激活时持续黄灯的解决办法
  17. Codeforces Round #807 (Div. 2)(A-D)
  18. 计算机少儿编程考级,少儿编程能力怎么评定?有什么考级可以参加?
  19. 安卓手机如何直接跟Mac电脑互传文件
  20. 苹果Mac合上屏幕怎样才能不休眠?

热门文章

  1. 【C 语言】文件操作 ( 文件结尾判定 )
  2. 【Android CPU 优化】Android CPU 调优 ( Trace 文件分析 | Android Profiler 工具 | CPU Profiler 工具 )
  3. 阶段1 语言基础+高级_1-3-Java语言高级_02-继承与多态_第5节 final关键字_1_final关键字概念与四种用法...
  4. idea springboot配置外置tomcat好处
  5. 51Nod 1453 抽彩球
  6. Oracle安装步骤及PL/SQL Developer连接数据库
  7. poj 1379 模拟退火法
  8. 黑马程序员——Java正则表达式
  9. 汇编实验注意点(待补充和更新)
  10. Matlab GUI 界面设计基础(1)