• 不相交集的求并算法(按集合大小求并+按高度求并)


    【0】README

    0.1)本文总结于 数据结构与算法分析, 但源代码均为原创,旨在实现 不相交集ADT的两个操作:合并集合union+查找集合find;
    0.2) 不相交集ADT 的 Introduction , 参见 http://blog.csdn.net/PacosonSWJTU/article/details/49716905


    【1】灵巧求并算法——按集合大小求并

    1.1)大小求并法定义:上面的Union执行是相当任意的, 通过使第二棵树 成为第一棵树的子树而完成合并;对其的改进是借助任意的方法打破现有关系, 使得总让较小的树成为较大树的子树,我们把这种方法叫做 大小求并法
    1.2)可以看到, 如果Union 操作都是按照大小求并的话,那么任何节点的深度均不会超过 logN;
    1.3)首先注意节点的深度为0, 然后它的深度随着一次 Union 的结果而增加的时候,该节点则被置于至少是 它以前所在树两倍大的一棵树上;因此,它的深度最多可以增加 logN次;

    • 1.3.2) Find 操作 的运行时间为 O(logN), 而连续M次操作则花费 O(MlogN);
    • 1.3.3) 下图指出在16次Union操作后可能得到这种最坏的树;而且如果所有的Union都对相等大小的树进行, 那么这样的树是会得到的;
      这里写图片描述

    1.4)为了实现这种方法, 我们需要记住每个树的大小。由于我们实际上只使用一个数组,因此可以让每个根的数组元素包含它 的树的大小的负值;
    1.5)已经证明:若使用按大小求并则连续 M次运算需要 O(M)平均时间, 这是因为 当随机的Union执行时, 整个算法一般只有一些很小的集合(通常是一个元素)与 大 集合 合并;

    1.6)souce code + printing

    • 1.6.1)download source code :
      https://github.com/pacosonTang/dataStructure-algorithmAnalysis/blob/master/chapter8/p203_unionBySize.c
    • Source Code Statements:
      • S1)显然,本源代码只对元素的size进行了加,没有减;因为我想的话, 元素只能合并一次,也即是元素C起初合并到了集合A,就不能再次合并到集合B, 元素C就一直属于集合A的子集了;
      • S2)当然,这个代码只是 大致上实现了按大小求并的思想,如果元素C还可以再次合并到其他集合的话,这就涉及到集合根元素的size的加减问题了;需要的话,添加之即可;
    • 1.6.2)souce code at a glance
    #include <stdio.h>
    #include <malloc.h>
    
    #define ElementType int
    #define Error(str) printf("
     error: %s 
    ",str) 
    
    struct UnionSet;
    typedef struct UnionSet* UnionSet;
    
    // we adopt the child-sibling expr
    struct UnionSet
    {
    	int parent;
    	int size;
    	ElementType value;
    };
    
    UnionSet makeEmpty(); 
    UnionSet* initUnionSet(int size, ElementType* data);
    void printSet(UnionSet* set, int size);
    void printArray(ElementType data[], int size);
    int find(ElementType index, UnionSet* set);
    
    // initialize the union set 
    UnionSet* initUnionSet(int size, ElementType* data)
    {
    	UnionSet* set;	
    	int i;
    
    	set = (UnionSet*)malloc(size * sizeof(UnionSet));
    	if(!set)
    	{
    		Error("out of space, from func initUnionSet");        
            return NULL;
    	}	
    
    	for(i=0; i<size; i++)
    	{
    		set[i] = makeEmpty();
    		if(!set[i])
    			return NULL;
    		set[i]->value = data[i];
    	}
    	
    	return set;
    }
    
    // allocate the memory for the single UnionSet and evaluate the parent and size -1
    UnionSet makeEmpty()
    {
    	UnionSet temp;
    
    	temp = (UnionSet)malloc(sizeof(struct UnionSet));
    	if(!temp)
    	{
    		Error("out of space, from func makeEmpty!");        
    		return NULL;
    	}
    
    	temp->parent = -1;
    	temp->size = 1;
    	return temp;
    }
    
    // merge set1 and set2 by size
    void setUnion(UnionSet* set, int index1, int index2)
    {
    	//judge whether the index1 or index2 equals to -1 ,also -1 represents the root
    	if(index1 != -1)
    		index1 = find(index1, set);
    	if(index2 != -1)
    		index2 = find(index2, set);
    
    	if(set[index1]->size > set[index2]->size)
    	{
    		set[index2]->parent = index1;
    		set[index1]->size += set[index2]->size;
    	}
    	else
    	{
    		set[index1]->parent = index2;
    		set[index2]->size += set[index1]->size;
    	}
    } 
    
    //find the root of one set whose value equals to given value
    int find(ElementType index, UnionSet* set) 
    {
    	UnionSet temp;	
    	
    	while(1)
    	{
    		temp = set[index];
    		if(temp->parent == -1)
    			break;
    		index = temp->parent;
    	}
    
    	return index;		
    }	
    
    int main()
    {
    	int size;
    	UnionSet* unionSet;
    	ElementType data[] = {110, 245, 895, 658, 321, 852, 147, 458, 469, 159, 347, 28};
    
    	size = 12;
    	printf("
    	====== test for union set by size ======
    ");
    	//printf("
    	=== the initial array is as follows ===
    ");
    	//printArray(data, size); 
    	
    	printf("
    	=== the init union set are as follows ===
    ");
    	unionSet = initUnionSet(size, data); // initialize the union set over
    	printSet(unionSet, size);
    	
    	printf("
    	=== after union(1,5) + union(2,5) + union(3,4) + union(4,5) ===
    ");
    	setUnion(unionSet, 1, 5);
    	setUnion(unionSet, 2, 5);
    	setUnion(unionSet, 3, 4);
    	setUnion(unionSet, 4, 5);
    	printSet(unionSet, size);
    
    	printf("
    	=== after union(9,8) + union(7,6) + union(3,6) ===
    ");
    	setUnion(unionSet, 9, 8);
    	setUnion(unionSet, 7, 6);
    	setUnion(unionSet, 3, 6);	
    	printSet(unionSet, size);
    
    	return 0;
    }
    
    void printArray(ElementType data[], int size)
    {
    	int i;
    
    	for(i = 0; i < size; i++)	 
    		printf("
    	 data[%d] = %d", i, data[i]);					 
    	printf("
    
    ");
    } 
    
    void printSet(UnionSet* set, int size)
    {
    	int i;
    	UnionSet temp;
    	
    	for(i = 0; i < size; i++)
    	{		
    		temp = set[i];
    		printf("
    	 parent[%d] = %d", i, temp->parent);				
    	}
    	printf("
    ");
    }
    
    
    • 1.6.3)printing result
      这里写图片描述

    【2】灵巧求并算法——按集合高度求并

    2.1)按高度求并定义: 另外一种方法是按照高度求并(按照高度求并是按大小求并的简单修改)(推荐)
    2.2)它同样保证所有的树的深入最多是 O(logN)。我们使得 浅的树 成为深 的树的子树,这是一种平缓算法, 因为只有当两颗相等深度的树求并时树的高度才会增加(此时树的高度增加1)。
    2.3)source code + printing result

    #include <stdio.h>
    #include <malloc.h>
    
    #define ElementType int
    #define Error(str) printf("
     error: %s 
    ",str) 
    
    struct UnionSet;
    typedef struct UnionSet* UnionSet;
    
    // we adopt the depth-sibling expr
    struct UnionSet
    {
    	int parent;
    	int height;
    	ElementType value;
    };
    
    UnionSet makeEmpty();
    UnionSet* initUnionSet(int depth, ElementType* data);
    void printSet(UnionSet* set, int depth);
    void printArray(ElementType data[], int depth);
    int find(ElementType index, UnionSet* set);
    
    // initialize the union set 
    UnionSet* initUnionSet(int size, ElementType* data)
    {
    	UnionSet* set;	
    	int i;
    
    	set = (UnionSet*)malloc(size * sizeof(UnionSet));
    	if(!set)
    	{
    		Error("out of space, from func initUnionSet");        
            return NULL;
    	}	
    
    	for(i=0; i<size; i++)
    	{
    		set[i] = makeEmpty();
    		if(!set[i])
    			return NULL;
    		set[i]->value = data[i];
    	}
    	
    	return set;
    }
    
    // allocate the memory for the single UnionSet and evaluate the parent and depth -1
    UnionSet makeEmpty()
    {
    	UnionSet temp;
    
    	temp = (UnionSet)malloc(sizeof(struct UnionSet));
    	if(!temp)
    	{
    		Error("out of space, from func makeEmpty!");        
    		return NULL;
    	}
    
    	temp->parent = -1;
    	temp->height = 0;
    	return temp;
    }
    
    // merge set1 and set2 by depth
    void setUnion(UnionSet* set, int index1, int index2)
    {
    	//judge whether the index1 or index2 equals to -1 ,also -1 represents the root
    	if(index1 != -1)
    		index1 = find(index1, set);
    	if(index2 != -1)
    		index2 = find(index2, set);
    
    	if(set[index1]->height > set[index2]->height)	
    		set[index2]->parent = index1;			
    	else if(set[index1]->height < set[index2]->height)	
    		set[index1]->parent = index2;		
    	else
    	{
    		set[index1]->parent = index2;
    		set[index2]->height++; // only if the height of both of subtrees is equal, the height increases one
    	}
    } 
    
    //find the root of one set whose value equals to given value
    int find(ElementType index, UnionSet* set) 
    {
    	UnionSet temp;	
    	
    	while(1)
    	{
    		temp = set[index];
    		if(temp->parent == -1)
    			break;
    		index = temp->parent;
    	}
    
    	return index;		
    }	
    
    int main()
    {
    	int size;
    	UnionSet* unionSet;
    	ElementType data[] = {110, 245, 895, 658, 321, 852, 147, 458, 469, 159, 347, 28};
    
    	size = 12;
    	printf("
    	====== test for union set by depth ======
    ");
    	//printf("
    	=== the initial array is as follows ===
    ");
    	//printArray(data, depth); 
    	
    	printf("
    	=== the init union set are as follows ===
    ");
    	unionSet = initUnionSet(size, data); // initialize the union set over
    	printSet(unionSet, size);
    	
    	printf("
    	=== after union(0, 1) + union(2, 3) + union(4, 5) + union(6, 7) + union(8, 9) + union(10 ,11) ===
    ");
    	setUnion(unionSet, 0, 1);
    	setUnion(unionSet, 2, 3);
    	setUnion(unionSet, 4, 5);
    	setUnion(unionSet, 6, 7);
    	setUnion(unionSet, 8, 9);	
    	setUnion(unionSet, 10, 11);	
    	printSet(unionSet, size);
    
    	printf("
    	=== after union(1, 3) + union(5, 7) + union(9, 11) ===
    ");
    	setUnion(unionSet, 1, 3);
    	setUnion(unionSet, 5, 7);
    	setUnion(unionSet, 9, 11);
    	printSet(unionSet, size);  
    	
    	printf("
    	=== after union(3, 7) + union(7, 11) ===
    ");
    	setUnion(unionSet, 3, 7);
    	setUnion(unionSet, 7, 11);	
    	printSet(unionSet, size); 
    
    	return 0;
    }
    
    void printArray(ElementType data[], int size)
    {
    	int i;
    
    	for(i = 0; i < size; i++)	 
    		printf("
    	 data[%d] = %d", i, data[i]);					 
    	printf("
    
    ");
    } 
    
    void printSet(UnionSet* set, int size)
    {
    	int i;
    	UnionSet temp;
    	
    	for(i = 0; i < size; i++)
    	{		
    		temp = set[i];
    		printf("
    	 parent[%d] = %d", i, temp->parent);				
    	}
    	printf("
    ");
    }
    
    
    • 2.3.3)printing results:
      这里写图片描述
  • 相关阅读:
    可分离卷积详解及计算量 Basic Introduction to Separable Convolutions
    全面解读Group Normalization,对比BN,LN,IN
    高斯混合模型(GMM)及MATLAB代码
    VLAD算法浅析, BOF、FV比较
    MATLAB 可以画的各种类型的图总结
    检测算法简介及其原理——fast R-CNN,faster R-CNN,YOLO,SSD,YOLOv2,YOLOv3
    深度学习图像配准 Image Registration: From SIFT to Deep Learning
    在IIS7里配置 ISAPI,运行dll程序,总提示下载dll
    iis7下配置php出现404.17错误的解决办法
    C# Acrobat打开pdf出错,提示Acrobat.AcroPDDocClass不能强制转换为Acrobat.CAcroPDDoc,使用com组件{9B4CD3E7-4981-101B-9CA8-9240CE2738AE},HRESULT: 0x80004002
  • 原文地址:https://www.cnblogs.com/pacoson/p/4947023.html
Copyright © 2020-2023  润新知