数据结构第五周笔记(3)——树(下)(慕课浙大版本--XiaoYu)

101 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第17天,点击查看活动详情

5.3 集合及运算

5.3.1 集合的表示及查找

  1. 集合运算:交,并,补,差,判定一个元素是否属于某一集合

  2. 并查集:集合并、查某元素属于什么集合

  3. 并查集问题中集合存储如何实现?

    1. 可以用树结构表示集合,树的每个结点代表一个集合元素

    2. image-20220708125448566对这样三棵树的存储方法

      1. 采用数组存储形式
      2. image-20220708130212563
      3. 上图中没有父节点的用负数来表示,Parent是它父节点的下标
    3. [例]:有10台电脑{123,.....,910},已知下列电脑之间已经实现了连接:
      122435475869610
      问:27之间,59之间是否是连通的?
      27是连通的,59不连通
      

      image-20220708124931978

集合运算

(1)查找某个元素所在的集合(用根结点表示)

int Find(SetType S[],ElementType X)
{
    //在数组S中查找值为X的元素所属的集合
    //MaxSize是全局变量,为数组S的最大长度
    int i;
    for(i = 0;i < MaxSize && S[i].Data != X; i++);
    if(i >= MaxSize) return -1;//未找到X,返回-1
    for(;S[i].Parent >= 0; i = S[i].Parent);//Parent的值为-1的时候就是找到根结点。i = S[i].Parent:原本指向i的位置现在跳到了s[i].Parent
    return i;//找到X所属集合,返回树根结点在数组S中的下标
}

5.3.2 集合的并运算

(2)集合的并运算

  1. 分别找到X1和X2两个元素所在集合树的根结点

  2. 如果它们不同根,则将其中一个根结点的父结点指针设置成另一个根结点的数组下标

    1. Union实现代码

    2. void Union(SetType S[ ],ElementType X1,ElementType X2 )
      {
          int Root1,Root2;
          Root1 = Find(S,X1);//得到X1与X2对应的树根
          Root2 = Find(S,X2);
          if( Root1 != Root2 ) S[Root2].Parent = Root1;//判断如果不是本身就是同一个集合的,如果是同一个集合的话就不需要做这个并的操作。不同则合并
      }
      

      为了改善合并以后的查找性能,可以采用小的集合合并到相对大的集合中。(修改Union函数)。也许树的高度不会增加

小测验:集合

已知a、b两个元素均是所在集合的根结点,且分别位于数组分量3和2位置上,其parent值分别为-3,-2。问:将这两个集合按集合大小合并后,a和b的parent值分别是多少?

-5,3

集合的定义与并查

#define MAXN 1000                  /* 集合最大元素个数 */
typedef int ElementType;           /* 默认元素可以用非负整数表示 */
typedef int SetName;               /* 默认用根结点的下标作为集合名称 */
typedef ElementType SetType[MAXN]; /* 假设集合元素下标从0开始 */
​
void Union( SetType S, SetName Root1, SetName Root2 )
{ /* 这里默认Root1和Root2是不同集合的根结点 */
    /* 保证小集合并入大集合 */
    if ( S[Root2] < S[Root1] ) { /* 如果集合2比较大 */
        S[Root2] += S[Root1];     /* 集合1并入集合2  */
        S[Root1] = Root2;
    }
    else {                         /* 如果集合1比较大 */
        S[Root1] += S[Root2];     /* 集合2并入集合1  */
        S[Root2] = Root1;
    }
}
​
SetName Find( SetType S, ElementType X )
{ /* 默认集合元素全部初始化为-1 */
    if ( S[X] < 0 ) /* 找到集合的根 */
        return X;
    else
        return S[X] = Find( S, S[X] ); /* 路径压缩 */