6.5 树与等价问题

  • 如何划分等价类
    假设集合 S 有 n 个元素,m个形如(x, y)(x, y ∈ S) 的等价偶对确定了等价关系R,求R
    a. 令S中的每个元素各自形成一个只含单个成员的子集,记作 S1 , S2 , … , Sn
    b. 重复读入 m 个偶对,对每个读入的偶对(x, y),判定 x 和 y 所属的子集。假设x ∈ Si , y ∈ Sj , 若 Si != Sj ,则将Si并入Sj,并置Si为空(或将Sj并入Si,并置Sj为空)。在m个偶对都被处理过后,S1 , S2 , … , Sn所有非空子集即为S 的R的等价类
    【其实就是构造只含单个成员的集合判定某个单元素所在的子集归并两个互不相交的集合成为一个集合

利用树型结构表示集合,并划分等价类

  • 以森林 F = ( T1, T2, … ,Tn ) 来表示上述集合 S,森林中的每一棵树 Ti ( i = 1, 2, … , n ) 表示 S 中的一个元素 一一 子集 Si (Si ⊂ S, i = 1, 2, … , n),树中的每个结点表示子集中的一个成员 x ( 结点结构采用双亲表示法,即设置一个指针域指向其双亲结点 ),约定根节点的成员 / 数据域兼作子集的名称
  • 如下图,(a) 表示子集 S1 = { 1, 3, 6, 9 },(b) 表示 S2 = {2, 8, 10 },© 表示 S3 = S1 U S2
    实现两棵树的并操作:只要将一棵子集树的根结点指向另一棵子集树的根结点即可。

在这里插入图片描述

  • 代码实现
#define MAX_TREE_SIZE 100
// 以下结构描述单个结点结构
typedef struct PTNode
{
	TElemType data; // 结点数据域
	int parent; // 双亲位置域,指示双亲的在表中的下标
} PTNode;
// 以下结构描述树结构
typedef struct
{
	PTNode nodes[MAX_TREE_SIZE];// 顺序表存放所有结点,0号单元弃用
	int r, n; // r 为根的下标,n 为结点总数
} PTree;

typedef PTree MFSet;

// 查找森林 / 集合S中结点i所在子集的根
// 时间复杂度为 O(d), d是子集 / 树 的深度
int find_mfset(MFSet S, int i)
{
	// 找集合 S 中 i 所在子集的根
	if(i < 1 || i > S.n)
	{
		return -1;
	}
	for(j = i; S.nodes[j].parent > 0; j=S.nodes[j].parent);
	return j;
}

// 合并森林 S 的两个互不相交的子集 的并集
// S.nodes[i], S.nodes[j] 分别是这两个子集的根结点 
// 时间复杂度为 O(1)
Status merge_mfset(MFSet &S, int i, int j)
{
	if(i < 1 || i > S.n || j < 1 || j > S.n)
	{
		return ERROR;
	}
	// 将其中一个子集的根结点指向另一个根结点即可
	S.nodes[i].parent = j;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值