#include <stdlib.h>
/** 并查集. */
typedef struct ufs_t {
int *p; /** 树的双亲表示法*/
int size; /** 大小. */
} ufs_t;
/**
* @brief 创建并查集.
* @param[in] n 数组的容量
* @return 并查集
*/
ufs_t* ufs_create(int n) {
ufs_t *ufs = (ufs_t*)malloc(sizeof(ufs_t));
int i;
ufs->p = (int*)malloc(n * sizeof(int));
for(i = 0; i < n; i++)
ufs->p[i] = -1;
return ufs;
}
/**
* @brief 销毁并查集.
* @param[in] ufs 并查集
* @return 无
*/
void ufs_destroy(ufs_t *ufs) {
free(ufs->p);
free(ufs);
}
/**
* @brief Find 操作,带路径压缩,递归版.
* @param[in] s 并查集
* @param[in] x 要查找的元素
* @return 包含元素x 的树的根
*/
int ufs_find(ufs_t *ufs, int x) {
if (ufs->p[x] < 0) return x; // 终止条件
return ufs->p[x] = ufs_find(ufs, ufs->p[x]); /* 回溯时的压缩路径*/
}
/** Find 操作,带路径压缩,迭代版.所谓的路径压缩,就是在每次查找时,令查找路径上的每个节点都直接指向根节点 */
static int ufs_find_iterative(ufs_t *ufs, int x) {
int oldx = x; /* 记录原始x */
while (ufs->p[x] >= 0) {
x = ufs->p[x];
}
while (oldx != x) {
int temp = ufs->p[oldx];
ufs->p[oldx] = x;
oldx = temp;
}
return x;
}
/**
* @brief Union 操作,将y 并入到x 所在的集合.
* @param[in] s 并查集
* @param[in] x 一个元素
* @param[in] y 另一个元素
* @return 如果二者已经在同一集合,并失败,返回-1,否则返回0
*/
int ufs_union(ufs_t *ufs, int x, int y) {
const int rx = ufs_find(ufs, x);
const int ry = ufs_find(ufs, y);
if(rx == ry) return -1;
ufs->p[rx] += ufs->p[ry];
ufs->p[ry] = rx;
return 0;
}
/**
* @brief 获取元素所在的集合的大小
* @param[in] ufs 并查集
* @param[in] x 元素
* @return 元素所在的集合的大小
*/
int ufs_set_size(ufs_t *ufs, int x) {
const int rx = ufs_find(ufs, x);
return -ufs->p[rx];
}
并查集
最新推荐文章于 2020-03-26 20:29:47 发布