美文网首页
《算法4第一章》笔记(八)动态连通性(1) quick-find

《算法4第一章》笔记(八)动态连通性(1) quick-find

作者: 烤地瓜次不次 | 来源:发表于2019-02-28 16:08 被阅读0次

    问题描述:

    动态连通性:输入为一列整数对,其中每个整数对都表示一个某种弄类型的对象,一堆整数p q可以被理解为“p和q是相连的”。当程序从输入中读取了整数对p q时,如果一直的所有整数对都不能说明p和q是相连的,那么则将这一对整数写入到输出中。

    • p和q称为触点。
    • p和q的通道称为分量。

    quick-find源码:

    import edu.princeton.cs.algs4.StdIn;
    import edu.princeton.cs.algs4.StdOut;
    
    public class UF {
        private int[] id;// 分量id(以触点作为索引)
        private int count;// 分量数量
    
        public UF(int N) {
            count = N;
            id = new int[N];
            // 初始化分量id
            for (int i = 0; i < N; i++) {
                id[i] = i;
            }
        }
    
        public int count() {
            return count;
        }
    
        public boolean connected(int p, int q) {
            return find(p) == find(q);
        }
    
        public int find(int p) {
            return id[p];
        }
    
        public void union(int p, int q) {
            int pID = find(p);
            int qID = find(q);
            if (pID == qID) return;
            for (int i = 0; i < id.length; i++) {
                if (id[i] == pID) id[i] = qID;
            }
            count--;
        }
    
        public static void main(String[] args) {
            int N = StdIn.readInt();
            UF uf = new UF(N);
            while(!StdIn.isEmpty()) {
                int p = StdIn.readInt();
                int q = StdIn.readInt();
                if (uf.connected(p, q)) continue;
                uf.union(p, q);
                StdOut.println(p + " " + q);
            }
            StdOut.println(uf.count + " components");
        }
    
    }
    

    程序输入取自tinyUF.text文件

    10
    4 3
    3 8
    6 5
    9 4
    2 1
    8 9
    5 0
    7 2
    6 1
    1 0
    6 7
    

    程序入口

    public static void main(String[] args) {
        int N = StdIn.readInt();// 读取触点数量
        UF uf = new UF(N);// 初始化N个分量
        while(!StdIn.isEmpty()) {
            int p = StdIn.readInt();
            int q = StdIn.readInt();// 读取整数对
            if (uf.connected(p, q)) continue;// 如果已经连通则忽略
            uf.union(p, q);// 归并分量
            StdOut.println(p + " " + q);// 打印链接
        }
        StdOut.println(uf.count + " components");
    }
    

    算法逻辑分析

    public int find(int p) {
        return id[p];
    }
    
    public void union(int p, int q) {
        // 将p和q归并到相同的分量中
        int pID = find(p);
        int qID = find(q);
        if (pID == qID) return;// 如果p和q已经在相同的分量之中则不需要采取任何行动
        // 将p的分量重命名为q的名字
        for (int i = 0; i < id.length; i++) {
            if (id[i] == pID) id[i] = qID;
        }
        count--;
    }
    

    算法复杂度分析

    • union()操作访问数组的次数在(N+3)到(2N+1)之间。N为id.length。
      1. 当整数对只有一个时,访问次数为2+(N+1)
      2. 当整数对的数量为N时,访问次数为2+N+(N-1)
    • 假设我们使用quick-find算法来解决动态连通性问题并且最后只得到了一个连通分量,那么这至少需要调用N-1次union()。
    • 即至少(N+3)(N-1) ~ N²次数组访问————我们马上可以猜想动态连通性的quick-find算法是平方级别的。

    相关文章

      网友评论

          本文标题:《算法4第一章》笔记(八)动态连通性(1) quick-find

          本文链接:https://www.haomeiwen.com/subject/ojqkuqtx.html