📜  使用优先级队列和阵列列表的最小生成树

📅  最后修改于: 2021-06-29 04:27:44             🧑  作者: Mango

给定没有自环的双向加权(正)图,任务是生成图的最小生成树。

例子:

方法

  • 首先,在给定图中找到具有最小成本/重量的边缘。
  • 将两个初始顶点(最小成本边的顶点A,B)添加到已访问/添加的集合中。
  • 现在,所有具有新添加的顶点的连接边都添加到优先级队列中。
  • 从优先级队列中弹出开销最小的顶点(将流行顶点的所有连接边添加到优先级队列中),并重复进行直到边数等于顶点1为止。
  • 通过使用优先级队列,时间复杂度将降低为(O(E log V)) ,其中E是边的数量,V是顶点的数量。
  • 配对类也用于存储权重。

下面是上述方法的实现:

// Java implementation of the approach
import java.io.*;
import java.util.*;
import java.lang.Comparable;
public class MST {
  
    // Pair class with implemented comparable
    static class Pair,
                                V extends Comparable >
        implements Comparable > {
  
        public final U a;
        public final V b;
  
        private Pair(U a, V b)
        {
            this.a = a;
            this.b = b;
        }
  
        @Override
        public boolean equals(Object o)
        {
            if (this == o)
                return true;
            if (o == null || getClass() != o.getClass())
                return false;
  
            Pair pair = (Pair)o;
            if (!a.equals(pair.a))
                return false;
            return b.equals(pair.b);
        }
  
        // Overriding so that objects in map
        // could find the object key
        @Override
        public int hashCode()
        {
            return 31 * a.hashCode() + b.hashCode();
        }
  
        @Override
        public String toString()
        {
            return "(" + a + ", " + b + ")";
        }
  
        @Override
        public int compareTo(Pair o)
        {
            return getV().compareTo(o.getV());
        }
        private U getU()
        {
            return a;
        }
        private V getV()
        {
            return b;
        }
    }
  
    static class Graph {
  
        int vertices;
        ArrayList[] edges;
  
        // This variable keeps the least cost edge
        static Pair,
                    Integer>
            minCostEdge;
  
        Graph(int vertices)
        {
            minCostEdge = new Pair<>(new Pair<>(1, 1),
                                     Integer.MAX_VALUE);
            this.vertices = vertices;
            edges = new ArrayList[vertices + 1];
            for (int i = 0; i <= vertices; i++) {
                edges[i]
                    = new ArrayList >();
            }
        }
  
        void addEdge(int a, int b, int weight)
        {
            edges[a].add(new Pair<>(b, weight));
  
            // Since its undirected, adding the
            // edges to both the vertices
            edges[b].add(new Pair<>(a, weight));
            if (weight < minCostEdge.b) {
                minCostEdge
                    = new Pair<>(new Pair<>(a, b), weight);
            }
        }
  
        void MST()
        {
  
            // Priority queue for applying heap
            PriorityQueue,
                               Integer> >
                priorityQueue
                = new PriorityQueue<>();
  
            // Adding all the connected vertices
            // of MinCostEdge vertex A to PQ
            Iterator > iterator
                = edges[minCostEdge.a.a].listIterator();
            while (iterator.hasNext()) {
                Pair pair
                    = iterator.next();
                priorityQueue.add(
                    new Pair<>(
                        new Pair<>(minCostEdge.a.a, pair.a),
                        pair.b));
            }
  
            // Adding all the connected vertices
            // of MinCostEdge vertex B to PQ
            iterator = edges[minCostEdge.a.b].listIterator();
            while (iterator.hasNext()) {
                Pair pair = iterator.next();
                priorityQueue.add(
                    new Pair<>(
                        new Pair<>(minCostEdge.a.b, pair.a),
                        pair.b));
            }
  
            // Set to check vertex is added or not
            Set addedVertices = new HashSet<>();
  
            // Set contains all the added edges and cost from source
            Set, Integer> > addedEdges
                = new HashSet<>();
  
            // Using the greedy approach to find
            // the least costing edge to the GRAPH
            while (addedEdges.size() < vertices - 1) {
  
                // Polling from priority queue
                Pair, Integer> pair
                    = priorityQueue.poll();
  
                // Checking wether the vertex A is added or not
                if (!addedVertices.contains(pair.a.a)) {
                    addedVertices.add(pair.a.a);
                    addedEdges.add(pair);
  
                    // Adding all the connected vertices with vertex A
                    iterator = edges[pair.a.a].listIterator();
                    while (iterator.hasNext()) {
                        Pair pair1
                            = iterator.next();
                        priorityQueue.add(
                            new Pair<>(
                                new Pair<>(pair.a.a, pair1.a),
                                pair1.b));
                    }
                }
  
                // Checking wether the vertex B is added or not
                if (!addedVertices.contains(pair.a.b)) {
                    addedVertices.add(pair.a.b);
                    addedEdges.add(pair);
  
                    // Adding all the connected vertices with vertex B
                    iterator = edges[pair.a.b].listIterator();
                    while (iterator.hasNext()) {
                        Pair pair1
                            = iterator.next();
                        priorityQueue
                            .add(
                                new Pair<>(
                                    new Pair<>(pair.a.b, pair1.a),
                                    pair1.b));
                    }
                }
            }
  
            // Printing the MST
            Iterator, Integer> > iterator1
                = addedEdges.iterator();
            System.out.println("((A"
                               + ", "
                               + "B)"
                               + ", "
                               + "Cost)");
            while (iterator1.hasNext()) {
                System.out.println(iterator1.next());
            }
        }
    }
  
    // Driver code
    public static void main(String[] args) throws IOException
    {
        // Initializing the graph
        Graph g = new Graph(9);
        g.addEdge(0, 1, 4);
        g.addEdge(0, 7, 8);
        g.addEdge(1, 2, 8);
        g.addEdge(1, 7, 11);
        g.addEdge(2, 3, 7);
        g.addEdge(2, 8, 2);
        g.addEdge(2, 5, 4);
        g.addEdge(3, 4, 9);
        g.addEdge(3, 5, 14);
        g.addEdge(4, 5, 10);
        g.addEdge(5, 6, 2);
        g.addEdge(6, 7, 1);
        g.addEdge(6, 8, 6);
        g.addEdge(7, 8, 7);
  
        // Appling MST
        g.MST();
    }
}
输出:
((A, B), Cost)
((6, 7), 1)
((6, 5), 2)
((1, 0), 4)
((2, 3), 7)
((5, 2), 4)
((3, 4), 9)
((2, 1), 8)
((2, 8), 2)