Minimum Spanning Tree using Priority Queue and Array List


To discover the least crossing tree of a chart, be ready to utilise a combination of a need line and a cluster list. To begin with, we initialise the need line with the edges of the chart, sorted by their weights in climbing order. At that point, we make a cluster list to store the edges of the least traversing tree. We more than once extricate the edge with the least weight from the need line and check in the event that including it in the cluster list makes a cycle. In the event that not, we include the edge of the least crossing tree. This preparation proceeds until all hubs are included within the tree. The coming cluster list contains the least−crossing tree of the chart.

Methods Used

  • Kruskal's Algorithm

  • Prim's Algorithm

Kruskal Algorithm

Kruskal's Calculation may be a ravenous calculation utilised to discover the least crossing tree (MST) of an associated weighted chart. It begins with a purge chart and iteratively includes the most limited edge that does not make a cycle until all vertices are associated. The calculation sorts the edges in a rising order based on their weights and employs a disjoint set of information structures to track the associated components. By selecting edges in an expanding arrangement of weight, Kruskal's Calculation guarantees that, as it were, the edges with the littlest weights are included within the MST, coming about in a tree that ranges all vertices with the least weight.

Algorithm

  • Based on their weights, sort the chart edges ascending.

  • Initialise a cluster list to store the least traversing tree.

  • Create a need line to handle the edges efficiently.

  • Initialise a parent cluster where each vertex is its own parent.

  • Iterate over the sorted edges. For each edge, check in the event that its endpoints have a place for distinctively associated components.

  • If they do, include the edge of the least−crossing tree and blend the associated components by upgrading the parent array.

  • Repeat until all edges have been handled or the least−crossing tree is complete.

  • The coming cluster list contains the least traversing tree of the chart.

Example

#include <iostream>
#include <vector>
#include <algorithm>

struct Edge {
    int source, destination, weight;
};

// Find operation for disjoint set data structure
int find(std::vector<int>& parent, int vertex) {
    if (parent[vertex] != vertex) {
        parent[vertex] = find(parent, parent[vertex]);
    }
    return parent[vertex];
}

// Union operation for disjoint set data structure
void unionSet(std::vector<int>& parent, std::vector<int>& rank, int x, int y) {
    int xRoot = find(parent, x);
    int yRoot = find(parent, y);
    if (rank[xRoot] < rank[yRoot]) {
        parent[xRoot] = yRoot;
    } else if (rank[xRoot] > rank[yRoot]) {
        parent[yRoot] = xRoot;
    } else {
        parent[yRoot] = xRoot;
        rank[xRoot]++;
    }
}

// Comparator function to sort edges by weight
bool compareEdges(const Edge& edge1, const Edge& edge2) {
    return edge1.weight < edge2.weight;
}

// Kruskal's Algorithm to find the minimum spanning tree
std::vector<Edge> kruskal(std::vector<Edge>& edges, int numVertices) {
    std::vector<Edge> minimumSpanningTree;
    std::vector<int> parent(numVertices);
    std::vector<int> rank(numVertices, 0);

    // Initialize parent array
    for (int i = 0; i < numVertices; i++) {
        parent[i] = i;
    }

    // Sort edges in ascending order of weight
    std::sort(edges.begin(), edges.end(), compareEdges);

    // Process each edge in sorted order
    for (const auto& edge : edges) {
        int sourceParent = find(parent, edge.source);
        int destinationParent = find(parent, edge.destination);

        // If including the edge does not create a cycle, add it to the MST
        if (sourceParent != destinationParent) {
            minimumSpanningTree.push_back(edge);
            unionSet(parent, rank, sourceParent, destinationParent);
        }
    }

    return minimumSpanningTree;
}

// Driver code
int main() {
    int numVertices = 4;
    std::vector<Edge> edges = {
        {0, 1, 5},
        {0, 2, 3},
        {1, 2, 1},
        {1, 3, 4},
        {2, 3, 2}
    };

    std::vector<Edge> minimumSpanningTree = kruskal(edges, numVertices);

    // Print the edges of the minimum spanning tree
    std::cout << "Minimum Spanning Tree Edges:\n";
    for (const auto& edge : minimumSpanningTree) {
        std::cout << edge.source << " - " << edge.destination << " : " << edge.weight << "\n";
    }

    return 0;
}

Output

Minimum Spanning Tree Edges:
1 - 2 : 1
2 - 3 : 2
0 - 2 : 3

Prim’s Algorithm

Prim's Algorithm could be an eager calculation that finds the least traversing tree (MST) of a weighted undirected chart. It begins with a subjective vertex and continuously includes the edge with the least weight that interfaces a gone−by vertex with an unvisited one. This handle proceeds until all vertices are gone. The calculation keeps up a need line to proficiently select the minimum−weight edge at each step. By over and over choosing the minimum−weight edge and including it in the MST, Prim's Algorithm ensures that the coming−about tree has the least added weight among all conceivable traversing trees on the chart.

Algorithm

  • Initialise a purge set in MST to store the least−crossing tree.

  • Select a self−assertive beginning vertex s from the graph.

  • Create a need line pq to store the edges with their weights.

  • Create a boolean cluster gone by to keep track of gone by vertices and initialise all vertices as unvisited.

  • Mark the beginning vertex as visited.

  • For each edge e associated with s, include e in pq.

  • While pq isn't empty:

  • Dequeue the edge e with the least weight from pq.

  • If the goal vertex v of e is now gone, proceed to the following iteration.

  • Add e to MST.

  • Mark V. has visited.

  • For each edge ne associated with v:

  • If the goal vertex nd of ne hasn't gone by, queue ne into pq.

  • Return MST, which speaks to the least traversing tree of the chart.

Example

#include <iostream>
#include <vector>
#include <queue>

using namespace std;

typedef pair<int, int> pii; // pair of vertex and weight

// Function to implement Prim's Algorithm for Minimum Spanning Tree
vector<vector<pii>> primMST(vector<vector<pii>>& graph, int startVertex) {
    int numVertices = graph.size();
    vector<bool> visited(numVertices, false);
    vector<vector<pii>> MST(numVertices);

    priority_queue<pii, vector<pii>, greater<pii>> pq; // min-heap priority queue
    pq.push(make_pair(0, startVertex)); // start with the given start vertex

    while (!pq.empty()) {
        int currentVertex = pq.top().second;
        int currentWeight = pq.top().first;
        pq.pop();

        if (visited[currentVertex])
            continue;

        visited[currentVertex] = true;

        // Traverse the neighbors of the current vertex
        for (const auto& neighbor : graph[currentVertex]) {
            int neighborVertex = neighbor.first;
            int neighborWeight = neighbor.second;

            if (!visited[neighborVertex])
                pq.push(make_pair(neighborWeight, neighborVertex));

            MST[currentVertex].push_back(make_pair(neighborVertex, neighborWeight));
            MST[neighborVertex].push_back(make_pair(currentVertex, neighborWeight));
        }
    }

    return MST;
}

// Driver code
int main() {
    int numVertices = 4;
    vector<vector<pii>> graph(numVertices);

    // Add edges to the graph (vertex, weight)
    graph[0].emplace_back(1, 4);
    graph[0].emplace_back(2, 1);
    graph[0].emplace_back(3, 3);
    graph[1].emplace_back(0, 4);
    graph[1].emplace_back(2, 2);
    graph[1].emplace_back(3, 1);
    graph[2].emplace_back(0, 1);
    graph[2].emplace_back(1, 2);
    graph[2].emplace_back(3, 5);
    graph[3].emplace_back(0, 3);
    graph[3].emplace_back(1, 1);
    graph[3].emplace_back(2, 5);

    int startVertex = 0;
    vector<vector<pii>> MST = primMST(graph, startVertex);

    // Print the Minimum Spanning Tree
    cout << "Minimum Spanning Tree (Adjacency List):" << endl;
    for (int i = 0; i < numVertices; ++i) {
        cout << "Vertex " << i << ": ";
        for (const auto& edge : MST[i]) {
            cout << "(" << edge.first << ", " << edge.second << ") ";
        }
        cout << endl;
    }

    return 0;
}

Output

Minimum Spanning Tree (Adjacency List):
Vertex 0: (1, 4) (2, 1) (3, 3) (2, 1) (1, 4) (3, 3) 
Vertex 1: (0, 4) (2, 2) (0, 4) (2, 2) (3, 1) (3, 1) 
Vertex 2: (0, 1) (0, 1) (1, 2) (3, 5) (1, 2) (3, 5) 
Vertex 3: (0, 3) (2, 5) (1, 1) (0, 3) (1, 1) (2, 5) 

Conclusion

This article gives clarification and usage of two calculations, Kruskal's Calculation and Prim's Calculation, for finding the least traversing tree of a chart. Kruskal's Calculation begins with a purge chart and iteratively includes the most limited edge that does not make a cycle until all vertices are associated. Prim's Calculation starts with a chosen beginning vertex and covetously includes the edge with the least weight that interfaces a gone−by vertex with an unvisited one. Both calculations utilise lines and cluster records to effectively prepare edges and vertices. The code illustrations given illustrate the execution of these calculations in C.

Updated on: 14-Jul-2023

264 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements