并查集类的c++封装,比較union_find algorithm四种实现方法之间的性能区别
问题描写叙述:
在计算机科学中,并查集是一种树型的数据结构,其保持着用于处理一些不相交集合(Disjoint
Sets)的合并及查询问题。有一个联合-查找算法(union-find algorithm)定义了两个操作用于此数据结构:
Find:确定元素属于哪一个子集。它能够被用来确定两个元素是否属于同一子集;
Union:将两个子集合并成同一个集合;
实现并查集的关键是实现union-find algorithm, 本文依据经常使用的四种算法,实现了这个类,详细算法实现请參看维基百科;
制造測试数据集,測试几种方法之间性能的指标;
程序代码:
#ifndef _DISJOINT_SET_H_
#define _DISJOINT_SET_H_ #include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <time.h>
#include <math.h> #include "windows.h" enum DISJOINTWAY
{
COMMON_WAY,
COMPREE_WAY,
WEIGHT_WAY,
WEIGHT_COMPRESS_WAY
}; /*
* encapsulate the class of disjoint set
*
*/ #define MAXDISJOINTSET 0xffffff
class DisjointSet
{
public:
DisjointSet( int maxSize = MAXDISJOINTSET ):m_item(0), m_size(maxSize)
{
m_item = new int[maxSize];
for( int i = 0; i < m_size; i++ )
{
m_item[i] = i;
} m_path = new int[maxSize];
memset( m_path, 1, sizeof(int)*maxSize );
} ~DisjointSet()
{
Clear();
} /*
* find interface
*
*/
int Find( DISJOINTWAY way, int input )
{
assert( input < m_size );
switch( way )
{
case COMMON_WAY:
return ImplFindFirst( input );
case COMPREE_WAY:
return ImplFindSecond( input );
case WEIGHT_WAY:
return ImplFindWeight( input );
case WEIGHT_COMPRESS_WAY:
return ImplFindWeightCompree( input );
default:
return -1;
}
} /*
* make union
*
*/
void Union( DISJOINTWAY way, int first, int second )
{
assert( first < m_size && second < m_size );
switch( way )
{
case COMMON_WAY:
ImplUnionFirst( first, second );
break;
case COMPREE_WAY:
ImplUnionSecond( first, second );
break;
case WEIGHT_WAY:
ImplUnionWeighted( first, second );
break;
case WEIGHT_COMPRESS_WAY:
ImplUnionCompree( first, second );
break;
default:
break;
} } /*
*
*
*/
void Clear()
{
delete [] m_item;
m_item = 0; delete [] m_path;
m_path = 0; m_size = 0;
} protected: int ImplFindFirst( int input )
{
assert( input < m_size );
return m_item[input];
} int ImplFindSecond( int input )
{
int i = input;
for( ; i != m_item[i]; i = m_item[i] ); return i;
} int ImplFindWeight( int input )
{
int i = input;
for( ; i != m_item[i]; i = m_item[i] ); return i; } int ImplFindWeightCompree( int input )
{
int i = input;
for( ; i != m_item[i]; i = m_item[i] )
m_item[i] = m_item[m_item[i]]; return i;
} /*
*
*
*/
void ImplUnionFirst( int first, int second )
{
int x = m_item[first];
int y = m_item[second]; if( x != y )
{
m_item[first] = y;
} for( int i = 0; i < m_size; i++ )
{
if( x == m_item[i] )
m_item[i] = y;
}
} /*
*
*
*/
void ImplUnionSecond( int& first, int& second )
{
if( first != second )
{
m_item[first] = second;
}
} /*
*
*
*/
void ImplUnionWeighted( int first, int second )
{
if( first != second )
{
if( m_path[first] < m_path[second] )
{
m_item[first] = second;
m_path[second] += m_path[first];
}
else
{
m_item[second] = first;
m_path[first] += m_path[second];
}
}
} /*
*
*
*/
void ImplUnionCompree( int first, int second )
{
if( first != second )
{
if( m_path[first] < m_path[second] )
{
m_item[first] = second;
m_path[second] += m_path[first];
}
else
{
m_item[second] = first;
m_path[first] += m_path[second];
}
} } protected: int* m_item;
int m_size; int* m_path; }; void TestDisjointSetSimple()
{
DisjointSet djoint;
int i = djoint.Find( COMMON_WAY, 1 );
int j = djoint.Find( COMMON_WAY, 3 );
if( i != j )
djoint.Union( COMMON_WAY, 1, 3 ); i = djoint.Find( COMMON_WAY, 2 );
j = djoint.Find( COMMON_WAY, 5 );
if( i != j )
djoint.Union( COMMON_WAY, i, j ); i = djoint.Find( COMMON_WAY, 2 );
j = djoint.Find( COMMON_WAY, 6 );
if( i != j )
djoint.Union( COMMON_WAY, i, j ); i = djoint.Find( COMMON_WAY, 6 );
j = djoint.Find( COMMON_WAY, 7 );
if( i != j )
djoint.Union( COMMON_WAY, i, j ); assert( djoint.Find( COMMON_WAY, 2 ) == djoint.Find( COMMON_WAY, 7 ) ); i = djoint.Find( COMMON_WAY, 1 );
j = djoint.Find( COMMON_WAY, 7 );
if( i != j )
djoint.Union( COMMON_WAY, i, j ); assert( djoint.Find( COMMON_WAY, 3 ) == djoint.Find( COMMON_WAY, 7 ) );
} void TestDisjointSetComplex( DISJOINTWAY way, const char* str )
{ unsigned long start = GetTickCount();
DisjointSet djoint; const int len = 1000000;
const int base = 60000;
int halfLen = len / 2;
srand( time(NULL) );
for( int i = 0; i < len; i++ )
{
int first = rand() % base;
int second = rand() % base;
if( i > halfLen )
{
first += base;
second += base;
} if( first != second )
{
first = djoint.Find( way, first );
second = djoint.Find( way, second );
if( first != second )
djoint.Union( way, first, second ); assert( djoint.Find( way, first ) == djoint.Find( way, second ) );
}
} unsigned long interval = GetTickCount() - start;
printf(" %s way consume time is %d \n", str, interval ); } void TestSuiteDisjointSet()
{
TestDisjointSetSimple(); const char* str[] = {"common", "compress", "weight", "weight compress"};
for( int i = WEIGHT_COMPRESS_WAY; i >= 0; i--)
{
TestDisjointSetComplex((DISJOINTWAY)i, str[i] );
} } #endif
compile and run in visual studio 2005
以下图片是几种方法执行时间之比較,最直白方法的时间到如今还没输出,所以就没有显示:
并查集类的c++封装,比較union_find algorithm四种实现方法之间的性能区别的更多相关文章
- 百度地图和高德地图坐标系的互相转换 四种Sandcastle方法生成c#.net帮助类帮助文档 文档API生成神器SandCastle使用心得 ASP.NET Core
百度地图和高德地图坐标系的互相转换 GPS.谷歌.百度.高德坐标相互转换 一.在进行地图开发过程中,我们一般能接触到以下三种类型的地图坐标系: 1.WGS-84原始坐标系,一般用国际GPS纪录仪记 ...
- get,post,put,delete四种基础方法对应增删改查
PUT,DELETE,POST,GET四种基础方法对应增删改查 1.GET请求会向数据库发索取数据的请求,从而来获取信息,该请求就像数据库的select操作一样,只是用来查询一下数据,不会修改.增加数 ...
- 四种Sandcastle方法生成c#.net帮助类帮助文档
方法一 前端时间在网上收集和自己平时工作总结整理了<干货,比较全面的c#.net公共帮助类>,整理完成上传github之后我又想,既然是帮助类,总得有个帮助文档于是乎想到了Sandcast ...
- 类与接口(二)java的四种内部类详解
引言 内部类,嵌套在另一个类的里面,所以也称为 嵌套类; 内部类分为以下四种: 静态内部类 成员内部类 局部内部类 匿名内部类 一.静态内部类 静态内部类: 一般也称"静态嵌套类" ...
- RBAC类在ThinkPHP中的四种使用方法
第一类:放在登陆控制器的登陆操作中 1.RBAC::authenticate(); 用于在用户表中查找表单提交的用户名的数据,实质上就是一条用户表查寻语句,=====> return M(mod ...
- 关于android studio中使用class.forname()方法动态获取类实例报NO CLASS FOUND异常的几种处理方法
最近在做一个项目的时候需要用到反射来回调子类的方法,但是在反射过程中总是在class.forname()方法抛出NO CLASS FOUND异常,经过几部检查,问题解决,在此总结一下引起该问题的原因 ...
- Hashtable类中的四种遍历方法对比
要遍历一个Hashtable,api中提供了如下几个方法可供我们遍历: keys() - returns an Enumeration of the keys of this Hashtable ke ...
- poj1456(贪心+并查集)
题目链接: http://poj.org/problem?id=1456 题意: 有n个商品, 已知每个商品的价格和销售截止日期, 每销售一件商品需要花费一天, 即一天只能销售一件商品, 问最多能买多 ...
- poj 2236 并查集
并查集水题 #include<cstdio> #include<iostream> #include<algorithm> #include<cstring& ...
随机推荐
- maven-bundle-plugin插件, 用maven构建基于osgi的web应用
maven-bundle-plugin 2.4.0以下版本导出META-INF中的内容到MANIFEST.MF中 今天终于把maven-bundle-plugin不能导出META-INF中的内容到Ex ...
- poj2823Sliding Window(线段树求最值)
链接 裸线段树 这题时间卡的挺棒 #include <iostream> #include<cstdio> #include<cstring> #include&l ...
- bzoj3294
感觉自己就是不怎么擅长计数的问题 设f[k,i,j]表示前k种颜色占据了i行j列的方案 g[k,i,j]表示第k种颜色占据了i行j列的方案,注意要减去并没占据满i行j列的情况 然后转移就很好写了 像这 ...
- Hibernate事务与并发问题处理(乐观锁与悲观锁)
目录 一.数据库事务的定义 二.数据库事务并发可能带来的问题 三.数据库事务隔离级别 四.使用Hibernate设置数据库隔离级别 五.使用悲观锁解决事务并发问题 六.使用乐观锁解决事务并发问题 Hi ...
- Android 主题动态切换框架:Prism
Prism(棱镜) 是一个全新的 Android 动态主题切换框架,虽然是头一次发布,但它所具备的基础功能已经足够强大了!本文介绍了 Prism 的各种用法,希望对你会有所帮助,你也可以对它进行扩展, ...
- Breaking parallel loops in .NET C# using the Stop method z
List<, , , , , , , , , }; Parallel.ForEach(integers, (int item, ParallelLoopState state) => { ...
- MSP430开学的序章
吐槽一下最近在搞什么~~~,星期三在等板子来,自己的板子,激动呀!!F5系列的板子,激动呀!结果板子到星期五才拿到!开始的时候,感觉自己没多大问题,结果一上手就问题百出,因为没仔细看用户手册,导致光盘 ...
- 面向对象(class0420)
测试 交换两个变量的值 int num1 = 5;int num2=6; 通过程序交换让num1 = 6,num2=5; 求两个数的最大值 (求三个数最大值) 求1-100之间所有奇数的和 找胖子,{ ...
- wuzhicms私密下载链接生成
加载函数库:load_function('content','content'); echo private_file('http://dev.wuzhicms.com/uploadfile/2014 ...
- bzoj 1176 Mokia(CDQ分治,BIT)
[题目链接] http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=96974 [题意] 定义查询操作与修改操作:1 x y z 为 ...