typescrpit实现并查集(UnionFind)
本文参考:https://labuladong.github.io/algo/2/21/52/
2022.7.30更新
新增节点数优化,合并时将节点数少的树并入节点数多的树中,减少对子节点的操作次数
class UnionFind {
// 联通分量数目
public size: number = 0
// 父节点列表
public publicList: number[]
// 节点分数(该节点下子节点的数量)
public rank: number[]
constructor(size:number = 0) {
this.size = size
this.publicList = new Array(size + 1)
this.rank = new Array(size + 1)
for (let i = 1; i <= size; i++) {
this.publicList[i] = i
this.rank[i] = 1
}
}
// 寻找根
public findRoot(n: number): number {
let nn
// 路径压缩
while (this.publicList[n] !== n) {
nn = n
n = this.publicList[n]
this.publicList[nn] = n
}
return n
}
public isConnected(a:number, b:number): boolean {
let rootA: number = this.findRoot(a)
let rootB: number = this.findRoot(b)
return rootA === rootB
}
// 联通a,b
public union(a:number, b:number): void {
if (this.isConnected(a, b)) return
this.size--
let rootA: number = this.findRoot(a)
let rootB: number = this.findRoot(b)
if (rootA === rootB) return
// 此处使用树中节点的个数进行优化,将节点少的树合并到节点多的树里面,这样可以减少路径压缩的操作次数
if (this.rank[rootA] >= this.rank[rootB]) {
this.publicList[rootB] = rootA
this.rank[rootA] += this.rank[rootB]
}
else {
this.publicList[rootA] = rootB
this.rank[rootB] += this.rank[rootA]
}
}
}
/* 测试样例
~function test() {
let uf = new UnionFind(6)// 1,2,3,4,5,6
uf.union(1, 2)
uf.union(1, 3)
uf.union(2, 4)
uf.union(5, 6)
console.log(uf.isConnected(6, 5))// true
console.log(uf.isConnected(2, 5))// false
console.log(uf.isConnected(1, 2))// true
console.log(uf.isConnected(2, 3))// true
// 只有设置了初始size,该值才是正确的
console.log(uf.size)// 2, 有两个联通树 【1,2,3,4】和【5,6】
// 只有各个树根节点的uf.rank值才是正确的
console.log(uf.rank[uf.findRoot(1)])// 4, 1号节点所在的树下有4个节点【1,2,3,4】
console.log(uf.rank[uf.findRoot(2)])// 4, 2号节点所在的树下有4个节点【1,2,3,4】
console.log(uf.rank[uf.findRoot(3)])// 4, 3号节点所在的树下有4个节点【1,2,3,4】
console.log(uf.rank[uf.findRoot(4)])// 4, 4号节点所在的树下有4个节点【1,2,3,4】
console.log(uf.rank[uf.findRoot(5)])// 2, 5号节点所在的树下有2个节点【5,6】
}()
*/