Prim's Minimum Spanning Tree Algorithm
Having covered Kruskal's MST algorithm in my last article, it seems only natural to now cover Prim's MST algorithm. Prim's algorithm is another Greedy Best First Search graph algorithm for finding the minimum spanning tree of an undirected weighted graph. Functionally, it is very similar to the priority queue Lazy implementation of Dijkstra's Algorithm.
The Graph
Seeing as we already developed a graph data structure and accompanying graph in my previous article on Kruskal's MST algorithm, we will use that same general data structure and graph, I have removed the sorted edge list from the graph data structure, as it is not required for Prim's algorithm.
struct Edge {
int from;
int to;
int weight;
Edge* next; //For use in adjacency list and edge list linked lists.
Edge(int f = 0, int t = 0, int wt = 0, Edge* n = nullptr) {
from = f; to = t; weight = wt; next = n;
}
bool operator<(const Edge& o) const {
return weight < o.weight;
}
bool operator>(const Edge& o) const {
return weight > o.weight;
}
bool operator==(const Edge& o) const {
return from == o.from && to == o.to;
}
bool operator!=(const Edge& o) const {
return (*this != o);
}
};
class Graph {
private:
Edge** adjlist;
int _E;
int _V;
public:
Graph(int vertex) {
_V = vertex; _E = 0;
adjlist = new Edge*[_V];
for (int i = 0; i < _V; i++)
adjlist[i] = nullptr;
}
void addEdge(int from, int to, int weight) {
for (Edge* t = adjlist[from]; t != nullptr; t = t->next)
if (t->to == to)
return;
adjlist[from] = new Edge(from, to, weight, adjlist[from]);
adjlist[to] = new Edge(to, from, weight, adjlist[to]);
_E++;
}
Edge* adj(int vertex) {
return adjlist[vertex];
}
int V() { return _V; }
int E() { return _E; }
};
We will be using the same graph that we used in the previous article as well:
void initSampleGraph(Graph& G) {
G.addEdge(1, 2, 1);
G.addEdge(1, 3, 3);
G.addEdge(2, 3, 3);
G.addEdge(2, 4, 6);
G.addEdge(3, 4, 4);
G.addEdge(4, 5, 5);
G.addEdge(3, 5, 2);
}
Prim's Algorithm
Prim's algorithm is a through and through Best First Search. If you are familiar with Dijkstra's Shortest Path algorithm, then Prim's will look VERY familiar.
Prims algorithm works by maintaining several sets as arrays: a parent pointer array (pred), an edge cost array(cost), and a visited array(seen). The main data structure though is a min-heap priority queue, for selecting the minimum edge weight vertex from each nodes adjacency list.
void prims(Graph& G) {
vector<bool> seen(G.V(), false);
vector<int> cost(G.V(), INT32_MAX);
vector<int> pred(G.V(), -1);
vector<Edge*> mst;
int mstcost = 0;
priority_queue<pair<int,int>, vector<pair<int,int> >, std::greater<pair<int,int> > > pq;
cost[1] = 0;
pq.push(make_pair(0, 1));
while (!pq.empty()) {
int curr = pq.top().second;
pq.pop();
if (!seen[curr]) {
seen[curr] = true;
for (Edge* t = G.adj(curr); t != nullptr; t = t->next) {
if (!seen[t->to] && cost[t->to] > t->weight) {
cost[t->to] = t->weight;
pred[t->to] = curr;
pq.push(make_pair(t->weight, t->to));
}
}
}
}
cout<<"MST: "<<endl;
for (int i = 0; i < G.V(); i++) {
if (pred[i] != -1) {
cout<<pred[i]<<" <-> "<<i<<" - "<<cost[i]<<endl;
mstcost += cost[i];
}
}
cout<<"MST Cost: "<<mstcost<<endl;
}
Output:
MST:
1 <-> 2 - 1
1 <-> 3 - 3
3 <-> 4 - 4
3 <-> 5 - 2
MST Cost: 10
If you recall the result we attained by using Kruskals algorithm on the same graph, than you know we have gathered the same answer. The version of Prim's Algorithm shown above is the priority first search implementation, which executes in time proportional to E log V where E is the number of edges and V is the number of vertices in the graph.
-
Lossless Compression Part III: Huffman Coding
-
Lossless Compression Part II: The LZ77 Algorithm
-
Lossless Compression Part I: Working with Bits in a Byte Oriented World
-
Bottom Up AVL Tree: The OG Self-Balancing Binary Search Tree
-
A Different Take on Merge Sort: Binary Search Trees?
-
Deleting Entries From Open-Address Hash tables
-
Transform any Binary Search Tree in to a Sorted Linked List
-
From Regular Expressions To NFA by way of Abstract Syntax Trees: Thompsons Construction
-
Extending Sedgewick's explicit Digraph NFA
-
Iterative In-order B Tree Traversal
Leave A Comment