集合及运算

可以用树表示集合,树的结点代表集合的元素
集合及运算

  • 存储结构

这里采用数组的存储形式

#define ElementType int
typedef struct SetNode
{
	ElementType data;
	ElementType parent;
}SetType;
int size=0;
  • 创建集合

因为创建不是要讨论的核心,为了方便,这里采用了暴力的创建方法
为了区分根结点以及哪个根结点更大,这里用根结点的parent标识,例如:根结点r1有3个孩子,则r1的parent就是-4(是负数就是根结点)

void CreateSet(SetType* s)
{
	
	s[0].data=1;s[0].parent=-3; 
	s[1].data=2;s[1].parent=1; 
	s[2].data=4;s[2].parent=1; 
	s[3].data=3;s[3].parent=-4; 
	s[4].data=8;s[4].parent=3; 
	s[5].data=7;s[5].parent=3; 
	s[6].data=5;s[6].parent=3;
	size=7;
}
  • 查找某个元素的根结点,返回根结点的下标

先找到查找元素的下标i
如果它的父结点大于0,说明不是根结点,递归找父结点的根结点,小于0,则找到了根结点,返回根结点的下标

ElementType Find(SetType* s,ElementType x)
{
	int i;
	for(i=0;i<size && s[i].data!=x;i++ );
	if(i>=size) return -1;//没找到
	if(s[i].parent>0)	return Find(s,s[i].parent);
	else return i;
}
  • 合并两个集合

将元素少的 根结点(r1)并在另一个根结点(r2)上
r2.parent等于两个根结点的parent之和
r1的parent等于r2的data

void Union(SetType* s,ElementType root1,ElementType root2)
{
	if(s[root1].parent<s[root2].parent)
	{
		s[root1].parent+=s[root2].parent;
		s[root2].parent=s[root1].data;
	}
	else
	{
		s[root2].parent+=s[root1].parent;
		s[root1].parent=s[root2].data;
	}
}
  • 输出和主函数(用来测试)
void PrintSet(SetType* s)
{
	
	for(int i=0;i<size;i++)
	{
		printf("%d---->%d\n",s[i].data,s[i].parent);
	}
}
int main(int argc, char** argv) {
	SetType s[10];
	CreateSet(s);
	PrintSet(s);
	printf("----------find-------------\n");
	printf("%d\n",Find(s,7));
	printf("----------Union-------------\n");
	Union(s,0,3);
	PrintSet(s);
	return 0;
}
  • 运行结果
    集合及运算