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】
}()
 */
posted @ 2022-07-30 17:21  ぃ往事深处少年蓝べ  阅读(25)  评论(0编辑  收藏  举报