并查集类的c++封装,比較union_find algorithm四种实现方法之间的性能区别

并查集类的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

以下图片是几种方法执行时间之比較,最直白方法的时间到如今还没输出,所以就没有显示:

<span>并查集类的c++封装,比較union_find algorithm四种实现方法之间的性能区别</span>

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/119066.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • prepareStatement语句

    prepareStatement语句JDBC中的——PreparedStatement预编译原理prepareStatement语句有三大好处:Statement.executeUpdate(“INSERTINTOtb1_students(name,age,sex,address)VALUES(‘”+var1+”‘,'”+var2+”‘,”+var3+”,'”+var4+”‘)”);​prepareStatement=connection.prepareStatement(“INSERTINTOtb1_stud

  • Java开发手册之应用分层「建议收藏」

    Java开发手册之应用分层「建议收藏」Java开发手册之应用分层

  • Java学习路线(完整详细版)超详细

    一门永不过时的编程语言——Java软件开发。Java编程语言占比:据官方数据统计,在全球编程语言工程师的数量上,Java编程语言以1000万的程序员数量位居首位。而且很多软件的开发都离不开Java编程,因此其程序员的数量最多。而在以Java编程为核心的开发领域中,javaEE程序员的需求量10年来一直居于首位!Java工程师就业:1.通过各大招聘网站统计,全国海量公司都在招聘J…

  • 代理模式(proxy)

    前言 代理模式是一个大类,而且会经常用到,它包含了远程代理,虚拟代理,防火墙代理等,当然还有动态代理了,学过spring的人应该不陌生。 各种代理模式样式差别很大,不容易从程序上辨认,但是可以从功能上认出来,今天我就举个例子聊聊代理模式最基本的样子,从例子中认识代理模式。 举例为静态代理的基本应用,稍后再介绍代理模式的一些特点。  情境引入      本次我们以滴滴为例…

  • 树莓派pico官方网站_树莓派pico参数

    树莓派pico官方网站_树莓派pico参数文章目录1树莓派PICO简介1.1简介1.2配置[^2]1.3引脚图1.4尺寸2安装2.1烧录固件2.2安装IDE(ThonnyIDE)2.3离线运行程序3基础3.01点亮板载LED灯3.02板载LED闪烁3.03LED流水灯3.04按键实验3.05外部中断(改进3.04按键实验)3.06定时器中断(改进3.02板载LED闪烁)3.07PWM脉冲宽度调制(实现板载LED呼吸灯)3.08I2C总线(使用SSD1306OLED屏幕)4传感器程序4.1温度传

    2022年10月14日
  • 网络编程bind函数详解(转载)

    网络编程bind函数详解(转载)注:该文转载自https://blog.csdn.net/zpznba/article/details/90763798bind函数如何选择绑定地址我们知道bind函数一般用在服务器代码中:s

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号