Code:
#ifndef MST_Algorithm
#define MST_Algorithm
#include <iostream>
#include <vector>
using namespace std;
struct pqData {
int keyWeight;
int keyDestinationVertex;
int keySourceVertex;
};
class Compare {
public:
bool operator()(const pqData& lhs, const pqData& rhs)const
{
return(lhs.keyWeight > rhs.keyWeight); //min priority
}
};
//create a priority-queue of pqData
priority_queue <pqData, vector <pqData>, Compare > pq;
class Edge {
public:
int sourceVertex;
int destinationVertex;
int edgeWeight;
Edge* nextEdge;
//default constructor: initalize all data to -1 and nextEdge to NULL.
Edge() {
sourceVertex = -1;
destinationVertex = -1;
edgeWeight = -1;
nextEdge = NULL;
}
//3 paramater constructor : integers source, destination, weight
//Assign to appropriate class variables
Edge(int source, int destination, int weight) {
sourceVertex = source;
destinationVertex = destination;
edgeWeight = weight;
nextEdge = nullptr;
}
};
class resultSetClass {
public:
int parent;
int weight;
//Default constructor: set all variables to value of -1
resultSetClass() {
parent = -1;
weight = -1;
}
};
class graph {
int numberOfVertices;
vector<Edge*> adjacencyListGraph;
vector<Edge*> adjacencyListMST;
public:
/*default constructor:
Set numberOfVertices to zero
display messsage “Default - Empty Graph Created”*/
graph() {
numberOfVertices = 0;
cout << "Default - Empty Graph Created" << endl;
}
/*1 parameter constructor: integer vertices
Set numberOfVertices to vertices
initialize adjacencyListGraph for each vertex as empty list; points to edge
object*/
graph(int vertices) {
numberOfVertices = vertices;
adjacencyListGraph.resize(numberOfVertices, nullptr);
adjacencyListMST.resize(numberOfVertices, nullptr);
cout << "Graph Created with " << numberOfVertices << " vertices" << endl;
}
void addEdge(int source, int destination, int weight) {
if (adjacencyListGraph.size() == 0) {
cout << "Empty Graph - Cannot Add Edge: " << source << ", " << destination << ", " << weight << endl;
return;
}
else if (source < 0 || source >= numberOfVertices || destination < 0 || destination >= numberOfVertices) {
cout << "Invalid Source or Destination Vertex - Cannot Add Edge: " << source << ", " << destination << ", " << weight << " - Edge request ignored" << endl;
return;
}
else if (weight <= 0) {
cout << "Invalid Weight - Cannot Add Edge: " << source << ", " << destination << ", " << weight << " - Edge request ignored" << endl;
return;
}
Edge* edge = new Edge(source, destination, weight);
edge->nextEdge = adjacencyListGraph[source];
adjacencyListGraph[source] = edge;
cout << "Edge Added: " << source << ", " << destination << ", " << weight << endl;
// Add edge for undirected graph
Edge* reverseEdge = new Edge(destination, source, weight);
reverseEdge->nextEdge = adjacencyListGraph[destination];
adjacencyListGraph[destination] = reverseEdge;
cout << "Edge Added: " << destination << ", " << source << ", " << weight << endl;
}
void printGraph() {
cout << "Full Graph - Adjacency List" << endl;
for (int i = 0; i < numberOfVertices; i++) {
cout << "Adj[" << i << "] -> ";
Edge* current = adjacencyListGraph[i];
while (current != nullptr) {
cout << "(" << current->destinationVertex << ", " << current->edgeWeight << ") ";
current = current->nextEdge;
}
cout << endl;
}
}
void primMST() {
pqData extractedPQData;
pqData intoPQData;
bool* mst = new bool[numberOfVertices];
memset(mst, false, sizeof(mst));
resultSetClass* resultSet = new resultSetClass [numberOfVertices];
int* weights =new int [numberOfVertices];
// Initialize weights to maximum integer value
for (int i = 0; i < numberOfVertices; i++) {
weights[i] = INT_MAX;
}
// Vertex 0 is the starting vertex
weights[0] = 0;
extractedPQData.keyWeight = weights[0];
extractedPQData.keyDestinationVertex = 0;
extractedPQData.keySourceVertex = 0;
// Add starting vertex to the priority queue
// Note: Replace this operation with the appropriate operation for your priority queue library
pq.push(intoPQData);
resultSet[0].parent = -1;
while (!pq.empty()) {
extractedPQData = pq.top();
pq.pop();
if (mst[extractedPQData.keyDestinationVertex]) {
continue;
}
mst[extractedPQData.keyDestinationVertex] = true;
if (extractedPQData.keyDestinationVertex != 0 || extractedPQData.keySourceVertex != 0) {
addEdge(extractedPQData.keySourceVertex, extractedPQData.keyDestinationVertex, extractedPQData.keyWeight);
resultSet[extractedPQData.keyDestinationVertex].parent = extractedPQData.keySourceVertex;
resultSet[extractedPQData.keyDestinationVertex].weight = extractedPQData.keyWeight;
}
// Update weights for adjacent vertices
Edge* current = adjacencyListGraph[extractedPQData.keyDestinationVertex];
while (current != nullptr) {
if (!mst[current->destinationVertex] && weights[current->destinationVertex] > current->edgeWeight) {
weights[current->destinationVertex] = current->edgeWeight;
intoPQData.keyWeight = current->edgeWeight;
intoPQData.keyDestinationVertex = current->destinationVertex;
intoPQData.keySourceVertex = extractedPQData.keyDestinationVertex;
pq.push(intoPQData);
}
current = current->nextEdge;
}
}
}
void printMST() {
int totalMSTWeight = 0;
vector<resultSetClass> resultSet;
cout << "Minimum Spanning Tree" << endl;
if (numberOfVertices == 0) {
cout << "Empty Graph - No MST" << endl;
return;
}
for (int i = 1; i < numberOfVertices; i++) {
cout << "Edge: " << i << " - " << resultSet[i].parent << " weight: " << resultSet[i].weight << endl;
totalMSTWeight += resultSet[i].weight;
}
cout << "Total cost of MST: " << totalMSTWeight << endl;
cout << "MST Graph - Adjacency List" << endl;
for (int i = 0; i < numberOfVertices; i++) {
cout << "Adj[" << i << "] -> ";
Edge* current = adjacencyListMST[i];
while (current != nullptr) {
cout << "(" << current->destinationVertex << ", " << current->edgeWeight << ") ";
current = current->nextEdge;
}
cout << endl;
}
}
~graph() {
// Deallocate objects in the adjacency list
for (int i = 0; i < numberOfVertices; i++) {
Edge* current = adjacencyListGraph[i];
while (current != nullptr) {
Edge* temp = current;
current = current->nextEdge;
delete temp;
}
}
}
};
#endif
#include <iostream>
#include <fstream>
#include "MST_Algorithm.h"
#include <vector>
#include <queue>
using namespace std;
int main() {
string outputfile;
string inputfile;
int numEdges = 0;
int numVertices = 0;
cout << "Welcome to the MST Test Program" << endl;
cout << "Enter output file name: ";
cin >> outputfile;
fstream ofile(outputfile);
if (!ofile)
{
cerr << outputfile << " cannot be opened - program terminated " << endl;
return 0;
}
cout << "Output file: " << outputfile << endl;
cout << "Test Default Scenario" << endl;
//Create an empty graph and test functionality – No MST
graph Graph;
//Graph.primMST();
Graph.printMST();
cout << "Testing File Data" << endl;
cout << "Enter file name for graph data: ";
cin >> inputfile;
cout << "File name for graph data: " << inputfile;
fstream ifile(inputfile);
ifile.seekg(0, ios::end);
if (!ifile) {
cerr << inputfile << " cannot be opened or does not exist- program terminated " << endl;
return 0;
}
else if (ifile.tellg() == 0) {
cerr << inputfile << " contains no data- program terminated " << endl;
return 0;
}
while (!ifile.eof()) {
int edge = 0;
int vertices = 0;
}
Graph.printGraph();
//Graph.primMST();
Graph.printMST();
//deallocate graph object
Graph.~graph();
//read from file to see if more graphs
//end graph loop
cout << "Thank you for running the MST Test Program written by Amalia Jamaludin(me)!" << endl;
ifile.close();
ofile.close();
return 0;
}
Program output:
Testing Default Scenario
Minimum Spanning Tree
Empty Graph - No MST
Testing File Data
File name for graph data: CIS-Land1.dat
Graph with 6 vertices and 9 edges will be created
Number of input edges to process is: 9
Edge Added: 0, 1, 1
Edge Added: 1, 0, 1
Edge Added: 1, 3, 5
Edge Added: 3, 1, 5
Edge Added: 3, 0, 3
Edge Added: 0, 3, 3
Edge Added: 3, 4, 1
Edge Added: 4, 3, 1
Edge Added: 1, 4, 1
Edge Added: 4, 1, 1
Edge Added: 1, 2, 6
Edge Added: 2, 1, 6
Edge Added: 5, 2, 2
Edge Added: 2, 5, 2
Edge Added: 2, 4, 4
Edge Added: 4, 2, 4
Edge Added: 5, 4, 4
Edge Added: 4, 5, 4
Full Graph - Adjacency List
Adj\[0\] -\> (1, 1) (3, 3)
Adj\[1\] -\> (0, 1) (3, 5) (4, 1) (2, 6)
Adj\[2\] -\> (1, 6) (5, 2) (4, 4)
Adj\[3\] -\> (1, 5) (0, 3) (4, 1)
Adj\[4\] -\> (3, 1) (1, 1) (2, 4) (5, 4)
Adj\[5\] -\> (2, 2) (4, 4)
Minimum Spanning Tree
Edge: 1 - 0 weight: 1
Edge: 2 - 4 weight: 4
Edge: 3 - 4 weight: 1
Edge: 4 - 1 weight: 1
Edge: 5 - 2 weight: 2
Total cost of MST: 9
MST Graph - Adjacency List
Adj\[0\] -\> (1, 1)
Adj\[1\] -\> (0, 1) (4, 1)
Adj\[2\] -\> (4, 4) (5, 2)
Adj\[3\] -\> (4, 1)
Adj\[4\] -\> (1, 1) (3, 1) (2, 4)
Adj\[5\] -\> (2, 2)
Thank you for running the MST Test Program written by John