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

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

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

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 谈谈.Net技术面试【转】

    谈谈.Net技术面试【转】

    2021年8月15日
    47
  • Mac如何修改host文件「建议收藏」

    Mac如何修改host文件「建议收藏」首先开启一个文件夹,点击上方【前往】-&gt;【前往文件夹】。 输入“/private/etc/hosts”,点击【前往】。 自动开启“etc”文件夹,找到【hosts文件】,并将其拉到桌面上才能修改桌面上的hosts文件。 “右键”桌面上hosts文件,选择【打开文件的应用程序】,使用【文字编辑】开启。 开启编辑hosts文件。 编辑完后就把桌面上的…

    2022年10月12日
    0
  • Java酒店管理系统_java酒店管理系统报告

    Java酒店管理系统_java酒店管理系统报告基于jsp+servlet+pojo+mysql实现一个javaee/javaweb的小型酒店管理系统,该项目可用各类java课程设计大作业中,小型酒店管理系统的系统架构分为前后台两部分,最终实现在线上进行小型酒店管理系统各项功能,实现了诸如用户管理,登录注册,权限管理等功能,并实现对各类小型酒店管理系统相关的实体进行管理。该小型酒店管理系统为一个采用mvc设计模式进行开发B/S架构项…

    2022年9月24日
    0
  • 说一下java的运行机制_Java运行机制是什么?「建议收藏」

    说一下java的运行机制_Java运行机制是什么?「建议收藏」不管是学习Java还是其他什么变成语言,我们不仅要了解它的特性,充分的使用Java语言完成各种程序开发工作,还要了解Java的运行机制。只有了解其底层的运行机制,才能更好的利用Java完成各项工作。Java运行机制是什么?Java程序运行时,必须经过编译和运行两个步骤。首先将后缀名师“.java”的源文件进行编译,最终生成后缀名为“.class”的字节码文件。然后Java虚拟机将编译后的字节码文件…

    2022年7月7日
    20
  • 报文学习四(LLDP协议)「建议收藏」

    报文学习四(LLDP协议)「建议收藏」1.LLDP出现的原因随着网络技术的发展,接入网络的设备的种类越来越多,配置越来越复杂,来自不同设备厂商的设备也往往会增加自己特有的功能,这就导致在一个网络中往往会有很多具有不同特性的、来自不同厂商的设备,为了方便对这样的网络进行管理,就需要使得不同厂商的设备能够在网络中相互发现并交互各自的系统及配置信息。LLDP(LinkLayerDiscoveryProtocol,链路层发现协议)就是用于这个目的的协议。当一个设备从网络中接收到其它设备的这些信息时,它就将…

    2022年6月2日
    112
  • PS 命令之get-adgroupmember!

    PS 命令之get-adgroupmember!如果get-adgroup是查询我们的用户组的话,那么Get-adgroupmember就是查询出我们的组的成员的的命令了,这个命令的使用方式多数场景和我们的上面命令get-adgroup一起使用了。我们先来看怎么得出某个组的成员

    2022年7月13日
    15

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

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