并查集数据结构的几种实现
Posted tobemaster
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了并查集数据结构的几种实现相关的知识,希望对你有一定的参考价值。
第一种实现
每一个节点都只是指向根节点
find是 常数时间复杂度的, union是 线性时间复杂度的。
class quickFind { int[] a; int count; void init (int N) { a = new int[N]; for (int i = 0; i < N; i++) { a[i] = i; } count = N; } boolean connected(int p , int q) { return find(p) == find(q); } int find (int p) { return a[p]; } void union(int p , int q) { int proot = find(p); int qroot = find(q); if (proot == qroot) { return; } for (int i = 0; i < a.length; i++) { if (a[i] == proot) { a[i] = qroot; } } count--; } }
第二种实现
每一个节点指向一个和自己在相同集合中的节点
find操作是树的高度时间复杂度,union操作也是 树的高度时间复杂度
class quickUnion { int[] a; int count; void init(int N) { a = new int[N]; for (int i = 0; i < N; i++) { a[i] = i; } count = N; } void find(p) { while (p != a[p]) p = a[p]; return p; } void union(int p, int q) { int proot = find(p); int qroot = find(q); if (proot == qroot) { return; } a[proot] = qroot; count--; } void connected(int p, int q) { return find(p) == find(q); } }
第三种实现其实是第二种实现的改良版本
因为第二种实现,当树的高度比较大,趋于链表的时候,时间复杂度会比较高,应该尽量减小树的高度
find时间复杂度logn,union时间复杂度logn
class quickUnion2 { int[] a; int count; int[] size; void init(int N) { a = new int[N]; size = new int[N]; for (int i = 0; i < N; i++) { a[i] = i; size[i] = 1; } count = N; } void find(p) { while (p != a[p]) p = a[p]; return p; } void union(int p, int q) { int proot = find(p); int qroot = find(q); if (proot == qroot) { return; } if (size[proot] < size[qroot]) { a[proot] = qroot; size[qroot] += size[proot]; } else { a[qroot] = proot; size[proot] += size[qroot]; } count--; } void connected(int p, int q) { return find(p) == find(q); } }
使用场景,比如 岛屿个数 问题,除了用深度优先搜索之外,还可以用 并查集数据结构来做。
以上是关于并查集数据结构的几种实现的主要内容,如果未能解决你的问题,请参考以下文章