The minimum spanning tree algorithm (Prim/kruskal algorithm) for ———— weighted graph of one province per day

Source: Internet
Author: User
Tags assert iterable
1. Data structure for edges with weights
/ **
 * This type of object can represent an edge in the graph
 * @author lhever February 19, 2017 at 5:10:49 pm
 * @version v1.0
 * /
public class Edge implements Comparable <Edge>
{
    private int v;
    private int w;
    private final double weight;

    / **
     * Construction
     *
     * @param v
     * @param w
     * @param weight
     * @author lhever February 19, 2017 at 5:14:30 pm
     * @since v1.0
     * /
    public Edge (int v, int w, double weight)
    {
        if (v <0)
        {
            throw new IllegalArgumentException ("The value of vertex v must be a non-negative integer");
        }
        if (w <0)
        {
            throw new IllegalArgumentException ("The value of vertex w must be a non-negative integer");
        }
        if (Double.isNaN (weight))
        {
            throw new IllegalArgumentException ("Weight cannot be NaN");
        }
        this.v = v;
        this.w = w;
        this.weight = weight;
    }

    / **
     * Return weight
     *
     * @return
     * @author lhever February 19, 2017 at 5:15:41 pm
     * @since v1.0
     * /
    public double weight ()
    {
        return weight;
    }

    / **
     * Returns one of the vertices of the edge v
     * @return
     * @author lhever February 19, 2017 at 5:15:54 pm
     * @since v1.0
     * /
    public int either ()
    {
        return v;
    }

    / **
     * Returns one vertex in addition to vertex that forms an edge
     * @param vertex
     * @return
     * @author lhever February 19, 2017 at 5:16:16 pm
     * @since v1.0
     * /
    public int other (int vertex)
    {
        if (vertex == v)
        {
            return w;
        } else if (vertex == w)
        {
            return v;
        } else
        {
            throw new IllegalArgumentException ("illegal vertex");
        }
    }

    @Override
    public int compareTo (Edge other)
    {
        if (this.weight () <other.weight ())
        {
            return -1;
        } else if (this.weight ()> other.weight ())
        {
            return 1;
        } else
        {
            return 0;
        }
    }

    public String toString ()
    {
        return String.format ("% d-% d% .5f", v, w, weight);
    }

    public static void main (String [] args)
    {
        Edge e = new Edge (4, 5, 78.98);
        System.out.println (e);
    }

}
2 Weighted Graph-free data structure
import java.util.ArrayList;
import java.util.List;

public class EdgeWeightedGraph
{
    private static final String NEWLINE = System.getProperty ("line.separator");
    private final int V;
    private int E;
    private List <Edge> [] adj;

    @SuppressWarnings ("unchecked")
    public EdgeWeightedGraph (int V)
    {
        if (V <0)
        {
            throw new IllegalArgumentException ("Number of vertices must be non-negative");
        }
        this.V = V;
        this.E = 0;
        adj = (List <Edge> []) new ArrayList [V];
        for (int v = 0; v <V; v ++)
        {
            adj [v] = new ArrayList <Edge> ();
        }
    }

    public EdgeWeightedGraph (EdgeWeightedGraph G)
    {
        this (G.V ());
        this.E = G.E ();
        for (int v = 0; v <G.V (); v ++)
        {
            List <Edge> li = new ArrayList <Edge> ();
            for (Edge e: G.adj [v])
            {
                li.add (e);
            }
            for (Edge e: li)
            {
                adj [v] .add (e);
            }
        }
    }

    public int V ()
    {
        return V;
    }

    public int E ()
    {
        return E;
    }

    private void validateVertex (int v)
    {
        if (v <0 || v> = V)
        {
            throw new IllegalArgumentException ("The vertex number" + v + "is not between 0 and" + (V-1) + ");
        }
    }

    / **
     * Add edges to undirected unweighted graph
     *
     * @param e
     * @author lhever February 19, 2017 at 5:34:00
     * @since v1.0
     * /
    public void addEdge (Edge e)
    {
        int v = e. either ();
        int w = e.other (v);
        validateVertex (v);
        validateVertex (w);
        adj [v] .add (e);
        adj [w] .add (e);
        E ++;
    }

    / **
     * Returns the adjacent edge of vertex v
     *
     * @param v
     * @return
     * @author lhever February 19, 2017 at 5:35:09 pm
     * @since v1.0
     * /
    public Iterable <Edge> adj (int v)
    {
        validateVertex (v);
        return adj [v];
    }

    / **
     * Returns the degree of vertex v (number of adjacent vertices)
     *
     * @param v
     * @return
     * @author lhever February 19, 2017 at 5:36:08 pm
     * @since v1.0
     * /
    public int degree (int v)
    {
        validateVertex (v);
        return adj [v] .size ();
    }

    / **
     * Returns all edges in an undirected weighting graph
     *
     * @return
     * @author lhever February 19, 2017 at 5:38:55 pm
     * @since v1.0
     * /
    public Iterable <Edge> edges ()
    {
        List <Edge> list = new ArrayList <Edge> ();
        for (int v = 0; v <V; v ++)
        {
            int selfLoops = 0;
            for (Edge e: adj (v))
            {
                // In an undirected graph, the same edge will appear in the adjacency list of the two endpoints of this edge. The condition here is> to avoid duplicate search
                if (e.other (v)> v)
                {
                    list.add (e);
                }
                // For self-loop, such as (5, 5, 0.8), when adding an edge, it will be added twice, but it is actually only one edge, so only one
                else if (e.other (v) == v)
                {
                    if (selfLoops% 2 == 0)
                    {
                        list.add (e);
                    }
                    selfLoops ++;
                }
            }
        }
        return list;
    }

    public String toString ()
    {
        StringBuilder s = new StringBuilder ();
        s.append (V + "" + E + NEWLINE);
        for (int v = 0; v <V; v ++)
        {
            s.append (v + ":");
            for (Edge e: adj [v])
            {
                s.append (e + "");
            }
            s.append (NEWLINE);
        }
        return s.toString ();
    }

    public static void main (String [] args)
    {

            // 0 —————— 6
            // / | \ |
            // / | \ |
            // / 1 2 |
            // / |
            // 5 ——————————— 4
            // \ /
            // \ /
            // \ /
            // \ /
            // 3

        EdgeWeightedGraph g = new EdgeWeightedGraph (7);

        Edge e1 = new Edge (0, 1, 0.7);
        g.addEdge (e1);

        Edge e2 = new Edge (0, 2, 4.5);
        g.addEdge (e2);

        Edge e3 = new Edge (0, 5, 5.0);
        g.addEdge (e3);

        Edge e4 = new Edge (0, 6, 3.1);
        g.addEdge (e4);

        Edge e5 = new Edge (5, 4, 2.9);
        g.addEdge (e5);

        Edge e6 = new Edge (6, 4, 7.8);
        g.addEdge (e6);

        Edge e7 = new Edge (3, 4, 9.7);
        g.addEdge (e7);

        Edge e8 = new Edge (3, 5, 6.0);
        g.addEdge (e8);

        System.out.println (g);


        EdgeWeightedGraph g1 = new EdgeWeightedGraph (g);
        System.out.println (g1);

    }

}
Deferred implementation of the 3 prim algorithm (when a new crosscutting edge is added to the tree to identify the failed edge)
import java.util.ArrayList;
import java.util.List;
import java.util.PriorityQueue;

/ **
 * Prim algorithm for finding the minimum spanning tree of undirected unweighted graph (delayed implementation)
 * @author xxx February 19, 2017 at 6:20:21 PM
 * @version v1.0
 * /
public class LazyPrimMST
{
    private static final double FLOATING_POINT_EPSILON = 1E-12;
    private double weight; // weight of minimum spanning tree
    private List <Edge> mst; // all edges of the minimum spanning tree
    private boolean [] marked; // if vertex v has been added to the minimum spanning tree, marked [v] = true
    private PriorityQueue <Edge> pq;

    public LazyPrimMST (EdgeWeightedGraph G)
    {
        mst = new ArrayList <Edge> ();
        pq = new PriorityQueue <Edge> ();
        marked = new boolean [G.V ()];
        for (int v = 0; v <G.V (); v ++)
        {
            if (! marked [v])
            {
                prim (G, v);
            }
        }
        assert check (G);
    }

    private void prim (EdgeWeightedGraph G, int s)
    {
        scan (G, s);
        while (! pq.isEmpty ())
        {// It is best to stop when the minimum spanning tree contains v-1 edges
          // take out the edge with the smallest weight
            Edge e = pq.poll ();
            int v = e.either (), w = e.other (v);
            assert marked [v] || marked [w];

            if (marked [v] && marked [w])
            {
                continue;
            }
            mst.add (e); // edge e belongs to the edge of the minimum spanning tree
            weight + = e.weight ();

            // During the operation, the minimum spanning tree is gradually generated, here v is added to the current minimum tree
            if (! marked [v])
            {
                scan (G, v);
            }
            // During the operation, the minimum spanning tree is gradually generated, here v is added to the current minimum tree
            if (! marked [w])
            {
                scan (G, w);
            }
        }
    }

    / **
     * Add all adjacent edges of vertex v that meet the conditions to the priority queue,
     * The condition is: another vertex of these adjacent edges has not been added to the current minimum spanning tree (not yet visited)
     * @param G
     * @param v
     * @author xxx February 19, 2017 at 6:27:26 PM
     * @since v1.0
     * /
    private void scan (EdgeWeightedGraph G, int v)
    {
        assert! marked [v];
        marked [v] = true;
        for (Edge e: G.adj (v))
        {
            if (! marked [e.other (v)])
            {
                pq.add (e);
            }
        }
    }

    public Iterable <Edge> edges ()
    {
        return mst;
    }

    public double weight ()
    {
        return weight;
    }

    private boolean check (EdgeWeightedGraph G)
    {
        // verify that the weights are consistent
        double totalWeight = 0.0;
        for (Edge e: edges ())
        {
            totalWeight + = e.weight ();
        }
        if (Math.abs (totalWeight-weight ())> FLOATING_POINT_EPSILON)
        {
            System.err.printf ("The sum of the weights of all edges of the minimum spanning tree is not consistent with the result calculated by the weight () method:% f vs.% f \ n", totalWeight, weight ());
            return false;
        }

        // Use the connected search algorithm to determine whether it is an acyclic graph
        UnionFind UnionFind = new UnionFind (G.V ());
        for (Edge e: edges ())
        {
            int v = e.either (), w = e.other (v);
            if (UnionFind.connected (v, w))
            {
                System.err.println ("Not a tree forest");
                return false;
            }
            UnionFind.union (v, w);
        }

        // determine if it is a spanning tree
        for (Edge e: G.edges ())
        {
            int v = e.either (), w = e.other (v);
            if (! UnionFind.connected (v, w))
            {
                System.err.println ("Not a Spanning Tree");
                return false;
            }
        }

        // determine if it is a minimum spanning tree
        for (Edge e: edges ())
        {

            // all edges except e in the minimum spanning tree
            UnionFind = new UnionFind (G.V ());
            for (Edge f: mst)
            {
                int x = f.either (), y = f.other (x);
                if (f! = e)
                {
                    UnionFind.union (x, y);
                }
            }

            // check that e is min weight edge in crossing cut
            for (Edge f: G.edges ())
            {
                int x = f.either (), y = f.other (x);
                if (! UnionFind.connected (x, y))
                {
                    if (f.weight () <e.weight ())
                    {
                        System.err.println ("Edge" + f + "Segmentation violation");
                        return false;
                    }
                }
            }

        }
        return true;
    }

    public static void main (String [] args)
    {
        // 0 —————— 6
        // / | \ |
        // / | \ |
        // / 1 2 |
        // / |
        // 5 ——————————— 4
        // \ /
        // \ /
        // \ /
        // \ /
        // 3

    EdgeWeightedGraph g = new EdgeWeightedGraph (7);

    Edge e1 = new Edge (0, 1, 0.7);
    g.addEdge (e1);

    Edge e2 = new Edge (0, 2, 4.5);
    g.addEdge (e2);

    Edge e3 = new Edge (0, 5, 5.0);
    g.addEdge (e3);

    Edge e4 = new Edge (0, 6, 3.1);
    g.addEdge (e4);

    Edge e5 = new Edge (5, 4, 2.9);
    g.addEdge (e5);

    Edge e6 = new Edge (6, 4, 7.8);
    g.addEdge (e6);

    Edge e7 = new Edge (3, 4, 9.7);
    g.addEdge (e7);

    Edge e8 = new Edge (3, 5, 6.0);
    g.addEdge (e8);
    LazyPrimMST mst = new LazyPrimMST (g);
    for (Edge e: mst.edges ())
    {
System.out.println (e);
    }
    System.out.printf ("%. 5f \ n", mst.weight ());
   }

}


//////////////////// The code of the class used in the algorithm for connected search is as follows //////////////////////// ///////

import java.util.Arrays;

public class UnionFind {

    private int [] parent; // parent [i] is the parent (or root) of node i
    private byte [] rank; // rank [i] is the rank of the subtree with i as the root node
    private int count; // number of connected components


    / **
     * Initialize the data structure of a connectivity-finding algorithm, N represents the nodes (or vertices, or electric shock) in the data structure, and just initialized
     * Data structure, each node is located in its own connected component, that is, N connected components
     * @param N
     * @author xxx February 28, 2017 at 12:14:48 am
     * @since v1.0
     * /
    public UnionFind (int N)
    {
        if (N <0)
        {
            throw new IllegalArgumentException ();
        }
        count = N;
        parent = new int [N];
        rank = new byte [N];
        for (int i = 0; i <N; i ++)
        {
            parent [i] = i;
            rank [i] = 0;
        }
    }

    / **
     * Returns the id (or identifier) of the connected component containing node p
     * @param p
     * @return
     * @author xxx February 28, 2017 at 12:26:19 am
     * @since v1.0
     * /
    public int find (int p)
    {
        validate (p);
        while (p! = parent [p])
        {
            parent [p] = parent [parent [p]]; // path compression
            p = parent [p];
        }
        return p;
    }


    / **
     * Returns the total number of connected components
     * @return
     * @author xxx February 28, 2017 at 12:21:16 am
     * @since v1.0
     * /
    public int count ()
    {
        return count;
    }


    / **
     * True if node p and node q are in the same connected component
     * @param p
     * @param q
     * @return
     * @author xxx February 28, 2017 at 12:20:35 am
     * @since v1.0
     * /
    public boolean connected (int p, int q)
    {
        return find (p) == find (q);
    }

    / **
     * Combine connected components containing node p with connected components containing node q
     * @param p
     * @param q
     * @author xxx February 28, 2017 at 12:19:24 am
     * @since v1.0
     * /
    public void union (int p, int q)
    {
        int rootP = find (p);
        int rootQ = find (q);
        if (rootP == rootQ)
        {
            return;
        }

        // make root of smaller rank point to root of larger rank
        if (rank [rootP] <rank [rootQ])
        {
            parent [rootP] = rootQ;
        } else if (rank [rootP]> rank [rootQ])
        {
            parent [rootQ] = rootP;
        }

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.