Dynamic connectivity (动静连通性)

We assume "is connected to" is an equivalence relation

  • 自反性 Reflexive:

    p is connected to p.

  • 对称性 Symmetric:

    if p is connected to q, then q is connected to p.

  • 传递性 Transitive:

   if p is connected to q and q is connected to r, then p is connected to r.

Quick Find (eager algorithm)

public class QuickFindUF {    private int[] id;    public QuickFindUF(int N)    {        id = new int[N];        for (int i = 0; i < N; i++) {            id[i] = i;        }    }    public boolean connected(int p, int q)    {        return (id[p] == id[q]);    }    public void union(int p, int q)    {        int p_root = id[p];        int q_root = id[q];        for (int i = 0; i < id.length; i++) {            if (id[i] == p_root){                id[p] = q_root;            }        }    }}

Takes N^2 array accesses to process sequence of N union commands on N objects.(quadratic time is much to slow)

Quick Union (lazy approach)

package com.algorithm.week1;public class QuickUnionUF{    private int[] id;    public QuickUnionUF(int N)    {        id = new int[N];        //  设置每个对象的id为本人的初始索引(n次数组拜访)        for (int i = 0; i < N; i++) {            id[i] = i;        }    }    private int root(int i)    {        //  id[i] 是 i 的父节点,一直获取父节点直到达到根节点(获取的父节点不再变动)        // 数组的拜访次数取决于 i 的父节点的深度        //     7        //    / \        //   3   4        //  / \   \        // 5   6   1        // 例如上图 i 为 5 时父节点深度为 3         // 过程如下        // i: 5 id[5]: 3  =>  i: 3 id[3]: 7  =>  i: 7 id[7]: 7  =>  return 7        while (i != id[i]){            i = id[i];        }        return i;    }    public boolean connected(int p, int q)    {        // 查看 p 和 q 两者的根节点是否统一        // 数组的拜访次数取决于 p 和 q 父节点的深度        return root(p) == root(q);    }    public void union(int p, int q)    {        // 数组的拜访次数取决于 p 和 q 父节点的深度        int p_root = root(p);        int q_root = root(q);        // 将p的根节点指向q的根节点(p和q)        id[p_root] = q_root;    }}
algorithminitializeunionfind
quick-findNN1
quick-union
(worst case)
NN†
(† includes cost of finding roots)
N



Quick-find 毛病

  • Union 动作消耗较大(N次)
  • Trees 扁平,然而维持扁平的代价太大(须要for循环遍历更新每个元素更新父节点)

Quick-union 毛病

  • Trees 能够变得相当高
  • Find 代价太大(可能达到N次)