并查集类的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& ...
随机推荐
- 从Excel表格导入数据到数据库
数据库:SQL 1.小数据直接粘贴 2.用导入向导 3.用SSIS包 4.用SQL语句 现在详细说一下第4种方法,以.xlsx文件为例 .xlsx文件需要用provider“Microsoft.ACE ...
- ZJOI2010网络扩容
无限orz hzwer神牛…… 第一问很简单,按数据建图,然后一遍最大流算法即可. 第二问则需要用最小费用最大流算法,主要是建图,那么可以从第一问的残留网络上继续建图,对残留网络上的每一条边建 ...
- C# 向共享文件夹上传及下载文件
//第一步建立共享链接 public static bool connectState(string path, string userName, string passWord) { bool Fl ...
- LeetCode Product of Array Except Self (除自身外序列之积)
题意:给一个序列nums,要求返回一个序列ans,两序列元素个数相同,ans第i个元素就是除了nums[i]之外所有的数相乘之积. 思路:时间O(n),额外空间O(0). 第一次扫一遍,处理nums[ ...
- Rails常用命令
rails new Project rails g scaffold location uuid:string deviceid:string latitude:float longitude:flo ...
- HDU 5874 Friends and Enemies 【构造】 (2016 ACM/ICPC Asia Regional Dalian Online)
Friends and Enemies Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Othe ...
- order by优化--Order By实现原理分析和Filesort优化
在MySQL中的ORDER BY有两种排序实现方式: 1.利用有序索引获取有序数据 2.文件排序 在使用explain分析查询的时候,利用有序索引获取有序数据显示Using index.而文件排序显示 ...
- Base-Android快速开发框架(二)--数据存储之SharedPreferences
对于App开发者,抽象来说,其实就是将数据以各种各样的方式展示在用户面前以及采集用户的数据.采集用户的数据包括用户的输入.触摸.传感器等,展示的数据通过网络来源于各业务系统,以及用户的 输入数据.在这 ...
- JSP的笔记
JSP是一种特殊的Servlet,全称是java server page,属于服务器端语言 就JSP和Servle,HTML比较,三者的优缺点简略如下: Servlet: 缺点:不适合作为HTML的响 ...
- js特效第九天
offset家族(获取元素尺寸) offsetWidth得到对象的宽度,自己的,与他人无关 offsetWidth = width+border+padding,不包含margin offsetHei ...