树与集合-并查集

#include<stdio.h>
#include<stdlib.h>
#define MaxSize 50
typedef struct ufset {
	int parent[MaxSize];
	int size;
}UFset;

void CreateUFset(UFset* s, int n) {
	int i;
	s->size = n;
	for (i = 0; i < n; i++) {
		s->parent[i] = -1;
	}

}
int Find(UFset* s, int i) {
	for (; s->parent[i] >= 0; i = s->parent[i]);
	return i;
}
void Union(UFset* s,int x,  int y) {
	s->parent[x] = y;
}
int Find2(UFset* s, int i) {
	int r, t, l;
	for (r = i; s->parent[r] >= 0; r = s->parent[r]);
	if (i != r) {
		for (t = i; s->parent[t] != r; t = l) {
			l = s->parent[t];
			s->parent[t] = r;
		}
	}
	return r;
}
void Union2(UFset* s, int x, int y) {
	int temp = s->parent[x] + s->parent[y];
	if (s->parent[x] > s->parent[y]) {
		s->parent[x] = y;
		s->parent[y] = temp;
	}
	else {
		s->parent[y] = x;
		s->parent[x] = temp;
	}
}
int main() {
	UFset* s = (UFset*)malloc(sizeof(UFset));
	int i = 0;
	CreateUFset(s, 7);
	Union2(s, 2, 1);
	Union2(s, 3, 4);
	Union2(s, 3, 2);
	Union2(s, 6, 5);
	Union2(s, 3, 6);
		for (i = 0; i < s->size;i++) {
		printf("%d\t", s->parent[i]);
	}
	printf("\n%d\n",Find2(s, 5));
	for (i = 0; i < s->size; i++) {
		printf("%d\t", s->parent[i]);
	}
	printf("\n%d\n", Find2(s, 5));
	for (i = 0; i < s->size; i++) {
		printf("%d\t", s->parent[i]);
	}
	printf("\n%d\n", Find2(s, 1));
	for (i = 0; i < s->size; i++) {
		printf("%d\t", s->parent[i]);
	}
	printf("\n%d\n", Find2(s, 1));
	for (i = 0; i < s->size; i++) {
		printf("%d\t", s->parent[i]);
	}
	printf("\n%d\n", Find2(s, 0));
	for (i = 0; i < s->size; i++) {
		printf("%d\t", s->parent[i]);
	}
}

-1 2 3 -6 3 6 3
3
-1 2 3 -6 3 3 3
3
-1 2 3 -6 3 3 3
3
-1 3 3 -6 3 3 3
3
-1 3 3 -6 3 3 3
0
-1 3 3 -6 3 3 3
C:\C++程序&C++PrimerPlus\DataStructrue\树与集合-并查集\Debug\树与集合-并查集.exe (进程 19752)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .

笔记:
在Union2 进行创建子集时,如果x与y的parent相等,那么Union2(s, x ,y) 就是x为父结点,y为子节点。
在Find2执行的时候会打乱原有树的形状,每查找一次元素,都会使该元素直接连到父节点,使树变得扁平化,方便以后快速查找父节点。
笔记2:
以下为上述main函数下的各个元素的parent的变化情况,随附树的形状示意图。
请添加图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值