• 集合操作问题


     本博客的代码的思想和图片参考:好大学慕课浙江大学陈越老师、何钦铭老师的《数据结构》

    集合的操作

    1 引子

    集合运算: 交、并、补、差, 判定一个元素是否属于某一集合
    p 并查集:集合并、 查某元素属于什么集合
    p 并查集问题中集合存储如何实现?
    Ø 可以用树结构表示集合,树的每个结点代表一个集合元素

    例如,有三个整数集合
    S1={1,2,4,7}
    S2={3,5,8}
    S3={6,9,10}

    如何使用树来表示集合:

    我们可以使用双亲表示法,使用孩子指向父亲:

     

    当然我们也可以使用数组来进步表示:

     

    2 集合的运算

    2.1 表示集合的数据结构

     1 typedef int elementType;
     2 
     3  
     4 
     5 typedef struct node{
     6 
     7     elementType data;
     8 
     9     int parent;
    10 
    11 }coll,*pCollection;

    2.2 查找

    需求:给定一个元素,给定一个集合数组(多个集合可能在同一个数组中),查找该元素所属于的结合。要求返回集合的根元素的数组下标

    int Find( SetType S[ ], ElementType X ) 

    算法思想:

    a.首先对数组进行变量,看是否能找元素X,找到,使用i来记录这个元素X的下标

    若没有找到,直接返回-1

    b.在根据s[i].parent查找i的父节点,在把父节点的下标给i,一直查询到父节点的的parent=-1为止,此时的父节点就是根元素,把集合根节点的数组下标进行返回

    代码:

    int find(coll s[],elementType element){
    
        int i;
    
        for(i=0;i<MAXSIZE&&s[i].data!=element;i++);
    
        if(i>=MAXSIZE){/*在数组中没有找到该元素*/
    
            return -1;
    
        }
    
        for(;s[i].parent>=0;i=s[i].parent);
    
        return i;
    
    }

    2.3 合并集合

    需要:给定两个来自不同集合的元素,要求合并这两个集合

    返回:返回合并以后的集合的根元素

    void Union( SetType S[ ], ElementType X1, ElementType X2 ) 

    算法思想:

    a.首先使用find方法找到x1x2元素的根节点分别为root1root2

    b.root2节点指向root1节点,即把root2.parent=indexOf(root1)

    代码:

     1 void unionCollection(coll s[],elementType x1,elementType x2){
     2 
     3     int root1 = find(s,x1);
     4 
     5     int root2 = find(s,x2);
     6 
     7     if(roo1!=root2){
     8 
     9         s[root2].parent=root1;
    10 
    11     }
    12 
    13 }

    2.4 思考

    如果这样一直对集合进行合并,那么树的高度会一直增加,那么不利于树的查找,那么如何减少树的高度呢?

    需求:我们让小的集合指向大的集合,那么我们如何判断集合的大小呢?

    方法1:如果我们在集合的数据结构中添加一个size的属性,来表示集合的大小。这样是可以解决问题,但是我们发现,其实只有根节点需要size属性,其他元素是不需要size属性的,这样会造成空间的浪费。

    方法2:我们使用-1表示集合的根元素,那么我们能否使用使用-x 表示集合的大小,这是一个好的方法。既避免了空间的浪费,也解决了上面的问题。我们只需要在union方法进行修改即可。

    上述的代码在:collection.c可见。

  • 相关阅读:
    hdu 5053 the Sum of Cube
    [LeetCode] Word Pattern
    [LeetCode] Minimum Depth of Binary Tree
    [C++] std::vector
    [LeetCode] Count Binary Substrings
    [LeetCode] Degree of an Array
    [LeetCode] String to Integer (atoi)
    [LintCode] 比较字符串
    [LeetCode] Valid Parentheses
    [LeetCode] Perfect Number
  • 原文地址:https://www.cnblogs.com/yghjava/p/6751592.html
Copyright © 2020-2023  润新知