算法导论_不相交集合

#include <iostream>
#include <map>
using namespace std;
//不相交集合森林
typedef struct disjoint_set_forest_node{
	int value;//结点值
	disjoint_set_forest_node *parent;//父亲结点
	disjoint_set_forest_node *next;//next结点,形成单向循环链表
	int rank;//结点的秩
}disjoint_set_forest_node,*pDisjoint_set_forest_node;

pDisjoint_set_forest_node make_set(int value)
{
	pDisjoint_set_forest_node pdfn=new disjoint_set_forest_node;
	pdfn->rank=0;
	pdfn->parent=pdfn;
	pdfn->value=value;
	pdfn->next=pdfn;//单向循环链表
	return pdfn;
}

pDisjoint_set_forest_node find_set(map<int,pDisjoint_set_forest_node>ma,int key)//递归版本
{
	if(ma[key]!=ma[key]->parent){
		ma[key]->parent=find_set(ma,ma[key]->parent->value);
	}
	return ma[key]->parent;
}

pDisjoint_set_forest_node find_set_iterator(map<int,pDisjoint_set_forest_node>ma,int key)//非递归版本
{
	pDisjoint_set_forest_node pdfn=ma[key];
	while(pdfn!=pdfn->parent){
		pdfn=pdfn->parent;		
	}//找根结点

	pDisjoint_set_forest_node pt=ma[key];
	pDisjoint_set_forest_node ptmp=pt;

	while(ptmp!=pdfn){
		ptmp=ptmp->parent;
		pt->parent=pdfn;
		pt=ptmp;
	}
	return pdfn;
}


void link(pDisjoint_set_forest_node px,pDisjoint_set_forest_node py)//合并2个结点
{
	if(px->rank<py->rank){
		px->parent=py;
	}else{
		py->parent=px;
		if(px->rank==py->rank){
			++px->rank;
		}
	}
	pDisjoint_set_forest_node ptmp=py->next;//连接两个单向循环链表,形成一个大的单向循环链表
	py->next=px->next;
	px->next=ptmp;
}

void union_dis(int x,int y,map<int,pDisjoint_set_forest_node>ma)//合并两颗树
{
	link(find_set(ma,x),find_set(ma,y));
}

void print_set(map<int,pDisjoint_set_forest_node>ma,int x)// 打印结点信息
{
	pDisjoint_set_forest_node pt=ma[x];
	pDisjoint_set_forest_node ptmp=pt;
	do{
		cout<<ptmp->value<<" ";
		ptmp=ptmp->next;
	}while(pt!=ptmp);
	cout<<endl;
}

int main()
{
	int n=16;
	pDisjoint_set_forest_node *pdf=new pDisjoint_set_forest_node[n];
	map<int,pDisjoint_set_forest_node>ma;//保存值和其对应的地址之间的关系
	for(int i=0;i<n;++i){
		pdf[i]=make_set(i);
		ma[i]=pdf[i];
	}
	for(int i=0;i<n;i+=2){
		union_dis(i,i+1,ma);
	}
	for(int i=0;i<n-3;i+=4){
		union_dis(i,i+2,ma);
	}
	union_dis(0,4,ma);
	union_dis(10,12,ma);
	union_dis(0,9,ma);		
	cout<<find_set(ma,10)->value<<endl;
	cout<<find_set(ma,15)->value<<endl;
	for(int i=0;i<n;++i){
		print_set(ma,i);
	}
	for(int i=0;i<n;++i){
		delete ma[i];
	}
	delete [] pdf;
}

#include <iostream>
#include <map>
using namespace std;
struct queue;//声明

typedef struct disjoint_set_node{
	queue *represent;//指向该结点的代表
	int value;
	disjoint_set_node *next;//下一个结点指针
}disjoint_set_node,*pDisjoint_set_node;

typedef struct queue{
	disjoint_set_node *head;
	disjoint_set_node *tail;
	int size;
}queue,*pQueue;

pQueue make_set(int value)//创建结点集合
{
	pQueue qu=new queue;
	pDisjoint_set_node pd=new disjoint_set_node;
	pd->value=value;
	pd->next=NULL;
	pd->represent=qu;
	qu->head=pd;
	qu->tail=pd;
	qu->size=1;
	return qu;
}

int find_set(pQueue *pq,map<int,int> ma,int c)//查找结点所属的集合
{
	return pq[ma[c]]->head->value;
}

void union_dis(pQueue &px,pQueue &py,map<int,int>& ma)//合并两个集合
{
	if(px && py && px!=py){
		int x_num=px->size,y_num=py->size;
		if(x_num<y_num){
			pQueue tmp=py;
			py=px;
			px=tmp;
		}
		px->size+=py->size;
		px->tail->next=py->head;//链接链表
		px->tail=py->tail;
		pDisjoint_set_node pd=py->head;
		for(int i=0;i<py->size;++i){			
			ma[pd->value]=ma[px->head->value];
			pd->represent=px;
			pd=pd->next;
		}		
		delete py;//将多余的头结点删除掉
		py=NULL;
		if(x_num<y_num){
			py=px;
			px=NULL;
		}
	}
}

void main()
{
	int n=16;
	pQueue *pq=new pQueue[n];
	map<int,int>ma;//存储结点所属集合索引
	int *c=new int[n];
	for(int i=0;i<n;++i){
		c[i]=i;
		pq[i]=make_set(c[i]);
		ma[c[i]]=i;
		cout<<"[ "<<c[i]<<" , "<<i<<" ] ";
	}
	cout<<endl;
	for(int i=0;i<n;i+=2){
		union_dis(pq[ma[c[i]]],pq[ma[c[i+1]]],ma);
	}
	for(int i=0;i<n-3;i+=4){
		union_dis(pq[ma[c[i]]],pq[ma[c[i+2]]],ma);
	}
	union_dis(pq[ma[c[0]]],pq[ma[c[4]]],ma);
	union_dis(pq[ma[c[10]]],pq[ma[c[12]]],ma);
	union_dis(pq[ma[c[0]]],pq[ma[c[9]]],ma);
	cout<<find_set(pq,ma,1)<<endl;
	cout<<find_set(pq,ma,8)<<endl;

	for(int i=0;i<n;++i){//删除结点信息
		if(pq[i]){
			pDisjoint_set_node pd=pq[i]->head;
			pDisjoint_set_node pt=pd;
			for(int j=0;j<pq[i]->size;++j){
				pt=pd;
				pd=pd->next;
				cout<<pt->value<<" ";
				delete pt;
			}
			delete pq[i];
			cout<<endl;
		}
	}
	cout<<endl;
	delete[]c;
	map<int,int>().swap(ma);
	ma.clear();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值