1. 程式人生 > >union-find演算法(陣列實現版)

union-find演算法(陣列實現版)

第一種通過遍歷所有節點更新根節點(使同一連通分量指向同一點):find較快 故稱這種做法為quick-find

QF.java

import edu.princeton.cs.algs4.StdDraw;
import edu.princeton.cs.algs4.StdOut;

public class QF {
    private int[] id;
    private int count;
    public QF(int N)
    {
        id = new int[N];
        for (int i = 0; i < N; ++i)
            id[i] = i;
        count = N;
    }
    public
boolean connect(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 l = find(p); int r = find(q); if (l == r) return; for (int i = 0; i < id.length; ++i) { if
(id[i] == l) id[i] = r; } --count; } public int count() { return count; } // for test public void display() { for (int i = 0; i < id.length; ++i) StdOut.println(i + "--" + id[i]); } public void draw() { StdDraw.setXscale(-1
,id.length + 2); StdDraw.setYscale(-1,id.length + 2); StdDraw.setPenRadius(0.07); for (int i = 0; i < id.length; ++i) { StdDraw.setPenColor(StdDraw.GREEN); StdDraw.point(i, id[i]); StdDraw.setPenColor(StdDraw.RED); StdDraw.text(i,id[i],Integer.toString(i)+ "--" + Integer.toString(id[i])); } } }

測試結果(測試程式碼見後面的main.java)

這裡寫圖片描述

這裡寫圖片描述

第二種 通過find演算法找出根節點通過連線根節點保持連通性(此時union速度提升 quick-union)
Fu.java

import edu.princeton.cs.algs4.StdDraw;
import edu.princeton.cs.algs4.StdOut;

public class FU {
    private int[] id;
    private int count;
    public FU(int N)
    {
        id = new int[N];
        for (int i = 0;i < N; ++i)
            id[i] = i;
        count = N;
    }
    public boolean connect(int p,int q)
    {
        return find(p) == find(q);
    }
    public int find(int p)
    {
        while (id[p] != p)
            p = id[p];
        return p;
    }
    public void union(int p,int q)
    {
        int l = find(p);
        int r = find(q);
        if (l == r) return;
        id[l] = r;
        --count;
    }
    public int count()
    {
        return count;
    }
    public void display()
    {
        for (int i = 0; i < id.length; ++i)
            StdOut.println(i + "--" + id[i]);
    }
    public void draw()
    {
        StdDraw.setXscale(-1,id.length + 2);
        StdDraw.setYscale(-1,id.length + 2);
        StdDraw.setPenRadius(0.07);
        for (int i = 0; i < id.length; ++i)
        {
            StdDraw.setPenColor(StdDraw.GREEN);
            StdDraw.point(i, id[i]);
            StdDraw.setPenColor(StdDraw.RED);
            StdDraw.text(i,id[i],Integer.toString(i)+ "--" + Integer.toString(id[i]));
        }
    }
}

測試結果:

這裡寫圖片描述

這裡寫圖片描述

第三種 保持節點個數最小的連通分量成為較大的連通分量的子樹(降低找根結點的複雜度) 即在原有的quick-union方法改進 成為 加權quick-union演算法

AFU.java

import edu.princeton.cs.algs4.StdDraw;
import edu.princeton.cs.algs4.StdOut;

public class AUF {
    private int[] id;
    private int[] sd;
    private int count;
    public AUF(int N)
    {
        id = new int[N];
        sd = new int[N];
        for (int i = 0; i < N; ++i)
        {
            id[i] = i;
            sd[i] = 1;
        }
        count = N;
    }
    public boolean connect(int p,int q)
    {
        return find(p) == find(q);
    }
    public int find(int p)
    {
        while (id[p] != p)
            p = id[p];
        return p;
    }
    public void union(int p,int q)
    {
        int l = find(p);
        int r = find(q);
        if (sd[l] > sd[r])
        {
            id[r] = l;
            sd[l] += sd[r];
        }
        else
        {
            id[l] = r;
            sd[r] += sd[l];
        }
    }
    public void display()
    {
        for (int i = 0; i < id.length; ++i)
            StdOut.println(i + "--" + id[i]);
    }
    public void draw()
    {
        StdDraw.setXscale(-1,id.length + 2);
        StdDraw.setYscale(-1,id.length + 2);
        StdDraw.setPenRadius(0.07);
        for (int i = 0; i < id.length; ++i)
        {
            StdDraw.setPenColor(StdDraw.GREEN);
            StdDraw.point(i, id[i]);
            StdDraw.setPenColor(StdDraw.RED);
            StdDraw.text(i,id[i],Integer.toString(i)+ "--" + Integer.toString(id[i]));
        }
    }
}

測試結果:
這裡寫圖片描述

這裡寫圖片描述

main.java

import edu.princeton.cs.algs4.In;
import edu.princeton.cs.algs4.StdOut;

public class Main {
    public static void main(String[] args)
    {
        In in = new In("test.txt");
        FU fu = new FU(10);
        QF qf = new QF(10);
        AUF auf = new AUF(10);
        while (!in.isEmpty())
        {
            int l = in.readInt();
            int r = in.readInt();
            fu.union(l, r);
            qf.union(l, r);
            auf.union(l, r);
        }
        //StdOut.println("quick- find 例項");
        //qf.display();
        //StdOut.println("quick- union 例項");
        //fu.display();
        StdOut.println("加權 quick- union 例項");
        auf.display();
        //qf.draw();
        //fu.draw();

        auf.draw();
    }
}

測試資料: test.txt

這裡寫圖片描述