5.3 集合的表示

集合的表示


看着浙大视频做的笔记,这些东西还是自己动手写一遍印象比较深刻。

  • 集合运算: 交、并、补、差、判定一个元素是否属于某个集合
  • 并集,查找属于哪个集合
  • 并集,查找问题中集合存储如何实现
  • 可以用树结构 表示集合,树的每一个结点表示一个结合元素。
    在这里插入图片描述
  • 采用数组存储形式
typedef struct{
	ElementType Data; //存储值
	int Parent;//双亲节点指针
}SetType;

在这里插入图片描述

集合运算

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

从元素一直往上找,知道到达根节点,就是到达了没有父节点的结点,就找到了元素所在的集合。

typedef struct{
	ElementType Data; //存储值
	int Parent;//双亲节点指针
}SetType;

//在数组中查找值为x的元素所在的集合
//MaxSize 为全局变量,为数组s的最大长度
int Find(SetType S[], ElementType X)
{
    int i = 0 ;
    for(i = 0;i < MaxSize && s[i]!= X ;i++);
    if(i >= MaxSize) return -1;//未找到元素X,返回-1
    for(;s[i].Parent >= 0; i = s[i].Parent );
    return i;//找到元素X所在的集合,返回根在数组中的下标	
}

2. 集合的并运算

  • 分别找到X和X2两个元素坐在集合数的 根节点
  • 如果他们不同根,则将 一个根节点的父节点指针设置为另一个根节点的数组下标。
typedef struct{
	ElementType Data; //存储值
	int Parent;//双亲节点指针
}SetType;

//将X1 X2放入同一个集合
void Union(SetType S[], ElementType X1, ElementType X2)
{
    int root1 = Find(S[], X1);
    int root2 = Find(S[], X2);
    if(root1 != root2) //如果两个元素不在一个集合内,
        s[root1].Parent = root2;
}

但是如果一直并集操作,集合数会变得越来越高,Find函数的效率会越来越低。因此我们做并集操作的时候,尽量把较小的树指向到较大的树上。此时我们就需要存储树的大小。由于除了根节点,其他的元素的 Parent 内存放了其父节点的位置,都**>0**,根节点处的 Parent 值为**-1**,小于零。因此可将树的大小存储在根节点的 Parent 内,例如数有5个节点,就在根节点的 Parent = -5
下面的代码是改进后的并集操作。

typedef struct{
    ElementType Data; //存储值
    int Parent;//双亲节点指针
}SetType;

//将X1 X2放入同一个集合
void Union(SetType S[], ElementType X1, ElementType X2)
{
    int root1 = Find(S[], X1);
    int root2 = Find(S[], X2);
    //如果两个元素不在一个集合内
    if(root1 != root2){
        //如果X1所在树节点数 大于 X2所在树节点数
        if( s[root1].Parent < s[root2].Parent ){
            s[root1].Parent += s[root2].Parent;//更新树的大小
            s[root2].Parent = root1;//将 X2所在树的根节点 指向 X1所在树的根节点
        }
        else{
            s[root2].Parent += s[root1].Parent;//更新树的大小
            s[root1].Parent = root2;
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值