并查集

2023/9/5 JavaScriptAlgorithm

原文:并查集从入门到出门 (opens new window)

class UnionFind {
  /**
   * @param {number[]} parent
   */
  constructor(parent) {
    this.parent = parent;
    const n = this.parent.length;
    this.size = new Array(n).fill(1);
    this.rank = new Array(n).fill(1);
  }

  /**
   * 直接查找
   * @param {number} x
   * @returns {number}
   */
  findDirect(x) {
    if (this.parent[x] === x) return x;
    return this.findDirect(this.parent[x]);
  }

  /**
   * 带路径压缩的查找
   * @param {number} x
   * @returns {number}
   */
  find(x) {
    if (this.parent[x] === x) return x;
    this.parent[x] = this.find(this.parent[x]);
    return this.parent[x];
  }

  /**
   * 直接求并
   * @param {number} x
   * @param {number} y
   */
  unionDirect(x, y) {
    const xRoot = this.find(x);
    const yRoot = this.find(y);
    if (xRoot !== yRoot) {
      this.parent[yRoot] = xRoot;
    }
  }

  /**
   * 按大小求并
   * @param {number} x
   * @param {number} y
   */
  unionBySize(x, y) {
    const xRoot = this.find(x);
    const yRoot = this.find(y);
    if (xRoot !== yRoot) {
      if (this.size[yRoot] <= this.size[xRoot]) {
        this.parent[yRoot] = xRoot;
        this.size[xRoot] += this.size[yRoot];
      } else {
        this.parent[xRoot] = yRoot;
        this.size[yRoot] += this.size[xRoot];
      }
    }
  }

  /**
   * 按秩求并
   * @param {number} x
   * @param {number} y
   */
  unionByRank(x, y) {
    const xRoot = this.find(x);
    const yRoot = this.find(y);
    if (xRoot !== yRoot) {
      if (this.rank[yRoot] <= this.rank[xRoot]) {
        this.parent[yRoot] = xRoot;
      } else {
        this.parent[xRoot] = yRoot;
      }
      if (this.rank[xRoot] === this.rank[yRoot]) {
        this.rank[xRoot]++;
      }
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
最近更新: 2024年08月26日 17:39:34