并查集
一个简单的并查集实现:
void init(void) { for(int i = 0; i < 10; i++) { par[i] = i; } } int find(int i) { if(i != par[i]) { return par[i] = find(par[i]); } else { return i; } } void union_connect(int i, int j) { int p = find(i); int q = find(j); if(p == q) { return; } else { par[q] = p; } }
带路径压缩的并查集
int find0(int i) { // 递归实现 if (i != par[i]) { par[i] = find0(par[i]); // 回溯时的压缩路径 } // 从 i 结点搜索到祖先结点所经过的结点都指向该祖先结点 return par[i]; } int main() { union_connect(1, 3); union_connect(3, 4); union_connect(4, 8); union_connect(8, 9); union_connect(5, 8); // 这里连接起来的话 par[1] 和 par[8] 变成 5,但是 3 和 4 不变 return 0; } int find1(int i) { // 迭代实现 int x = i; // 保存原来的节点 while(i != par[i]) { // 查找跟节点 i = par[i]; // 找到跟节点,用 i 记录下 } int k = x; // 退回原来的节点 while(k != i) { // 非递归路径压缩操作 int j = par[k]; // 用 j 暂存 par[k]的父节点 par[k] = i; // par[i]指向跟节点 k = j; // k 移到父节点 } return i; // 返回根节点的值 }