zoukankan      html  css  js  c++  java
  • 算法导论 第二十一章:不相交集合森林

            在不相交集合中的还有一种更快的实现中。用有根树来表示集合。

    树中的每一个成员指向其父节点。每棵树的根包括了代表(representative),而且是他自己的父节点。不相交森林即由多棵这种树组成,例如以下图所看到的:

    [注:(b)是(a)UNION(e,g)的结果]

    採用上述表示方法直观上并不比採用链表表示算法更快。可是能够通过“按秩合并”和“路径压缩”来提升效率。

    按秩合并(union by rank)

        对于每一个节点,用秩表示节点高度的一个上界。

    在按秩合并中,具有较小秩的跟在UNION操作中要指向具有较大秩的根。

    路径压缩(path compression):

       在FIND-SET操作中,利用这样的启示式策略来使查找路径上的每一个节点都直接指向根节点。(路径压缩不改变节点的秩)


    相关操作伪代码例如以下:

         须要说明的是。上述FIND-SET过程採用一种两趟方法(two-pass method):一趟是沿查找路径上升。直到根;第二趟是沿查找路径下降,以便更新每一个节点。使之直接指向根。


    不相交森林实现连通子图的完整代码例如以下:

    #include<iostream>
    #include<string>
    #include<cstdlib>
    #include<vector>
    
    using namespace std;
    
    typedef struct setNode{
    	char key;
    	int rank;
    	setNode *parent;
    	setNode(char k):key(k),rank(0),parent(NULL){}
    	}setNode;
    
    typedef struct Set{
    	setNode *root;
    	}Set;
    
    typedef struct edge{
    	char u;
    	char v;
    	}edge;
    
    setNode *Make_Set(char k)
    {
    	setNode *x=new setNode(k);
    	x->parent = x;
    	return x;
    	}
    
    setNode *Find_Set(setNode *x)
    {
    	if(x != x->parent)
    		x->parent=Find_Set(x->parent);
    	return x->parent;
    	}
    void Link(setNode *x,setNode *y)
    {
    	if(x->rank > y->rank)
    		y->parent = x;
    	else
    	{ 
    		x->parent = y;
    		if(x->rank == y->rank)
    			y->rank = y->rank + 1;
    		}
    	}
    void Set_Union(setNode *x,setNode *y)
    {
    	Link(Find_Set(x),Find_Set(y));
    	setNode *z=Find_Set(x);
    	}
    void forestSet_Create(Set forestSet[],char vertex[],int vNum)
    {
    	for(int i=0;i<vNum;i++)
    	{ 
    	    int index=(int)vertex[i];                  //eg.a->97,b->98,...
    		forestSet[index].root = Make_Set(vertex[i]);
    		}
    	}
    void Compute_conComponents(Set forestSet[],edge edgeArray[],int eNum)
    {//Compute the component forest
    	for(int i=0;i<eNum;i++)
    	{
    		setNode *set_u=forestSet[(int)edgeArray[i].u].root;
    		setNode *set_v=forestSet[(int)edgeArray[i].v].root;
    		if (Find_Set(set_u) != Find_Set(set_v))
    			Set_Union(set_u,set_v);
    		} 
    	}
    void Print_conComponents(Set forestSet[],char vertex[],int vNum)
    {//classify the forest and print the connect components and the representative
    	string representative;
    	for(int i=0;i<vNum;i++){
    		setNode *t;
    		t=Find_Set(forestSet[(int)vertex[i]].root);		
    		if(representative.find(t->key) == -1)     //the char t is not in representative 
    			representative += t->key;
    		}
    	cout<<"The representative of the forest:"<<representative<<endl;
    	
    	int repLen=representative.length();
    	vector<char> *ComponentsVec = new vector<char>[repLen];
       for(int i=0; i<vNum; i++)
       {	 
    		setNode *temp;
    		temp=Find_Set(forestSet[(int)vertex[i]].root);
    		int index=representative.find(temp->key);
    		ComponentsVec[index].push_back(vertex[i]);
    		}	    
    
       for(int i=0; i<repLen; i++)
    	{
    		cout<<"The connect component "<<i+1<<" is:";
    		for(int j=0; j<ComponentsVec[i].size(); j++)
    			cout<<ComponentsVec[i].at(j)<<"   ";
    		cout<<endl;
    		} 
    	}
    int main()
    {
    	char vertex[]={'a','b','c','d','e','f','g','h','i','j'};
    	edge edgeArray[]={{'b','d'},{'e','g'},{'a','c'},{'h','i'},{'a','b'},{'e','f'},{'b','c'}};	
    	int vNum=sizeof(vertex)/sizeof(char);
    	int eNum=sizeof(edgeArray)/sizeof(edge);
    	Set forestSet[256]={NULL};
    
    	forestSet_Create(forestSet,vertex,vNum);           //Create forest set
    	Compute_conComponents(forestSet,edgeArray,eNum);   //Computing the component forest
    	Print_conComponents(forestSet,vertex,vNum);
    	
    	return 0;
    	}
    
    执行结果:



    【注:若有错误。请指正~~~】


  • 相关阅读:
    AtCoder Beginner Contest 205
    Codeforces Round #725 (Div. 3)
    Educational Codeforces Round 110 (Rated for Div. 2)【A
    Codeforces Round #722 (Div. 2)
    AtCoder Beginner Contest 203(Sponsored by Panasonic)
    AISing Programming Contest 2021(AtCoder Beginner Contest 202)
    PTA 520 钻石争霸赛 2021
    Educational Codeforces Round 109 (Rated for Div. 2)【ABCD】
    AtCoder Beginner Contest 200 E
    Educational Codeforces Round 108 (Rated for Div. 2)【ABCD】
  • 原文地址:https://www.cnblogs.com/jzssuanfa/p/7101447.html
Copyright © 2011-2022 走看看