-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathWGraph.cpp
More file actions
193 lines (174 loc) · 6.01 KB
/
WGraph.cpp
File metadata and controls
193 lines (174 loc) · 6.01 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
/*
* Thomas Kim
* 2405924
* chukim@chapman.edu
* CPSC-350-01
* PA6
* WGraph File that creates a weighted graph for the matrix*/
#include "WGraph.h"
#include <ostream>
#include <iostream>
#include <fstream>
#include <iomanip>
#include "PQueue.h"
#include "position.h"
using namespace std;
//default constructor
WGraph::WGraph(){
m_size = 0;
m_adj = NULL;
m_conn = NULL;
}
//overloaded constructor
WGraph::WGraph(unsigned int sz){
m_size = sz;
//allocate sz * sz adj matrix
m_adj = new double*[sz];
m_conn = new double*[sz];
for(int i = 0; i < m_size; ++i){
m_adj[i] = new double[sz];
m_conn[i] = new double[sz];
}
//start with edges
for(int i = 0; i < m_size; ++i){
for(int j = 0; j < m_size; ++j){
m_adj[i][j] = std::numeric_limits<double>::max(); //essentially infinity
m_conn[i][j] = std::numeric_limits<double>::max();
}
}
}
//default deconstructor
WGraph::~WGraph(){
for(int i = 0; i < m_size; i++){
delete[] m_adj[i];
delete[] m_conn[i];
delete[] newCons[i];
}
delete m_adj;
delete m_conn;
delete newCons;
}
//adds edge and the weight to the m_adj matrix
void WGraph::addEdge(VertexID i, VertexID j, double w){
if(i < m_size && j < m_size){
m_adj[i][j] = w;
m_adj[j][i] = w;
}
}
//removes an edge given a vertex location
void WGraph::removeEdge(VertexID i, VertexID j){
if(i < m_size && j < m_size){
m_adj[i][j] = std::numeric_limits<double>::max();
m_adj[j][i] = std::numeric_limits<double>::max();
}
}
//checks if there is an adjacent
bool WGraph::areAdjacent(VertexID i, VertexID j){
return (m_adj[i][j] < std::numeric_limits<double>::max());
}
//calculates Floyd Warshael Algorithim
//doesnt apply to this project
void WGraph::calcFW(){ //runtime complexity O(v^3)
for(int i = 0; i < m_size; ++i){
for(int j = 0; j < m_size; ++j){
m_conn[i][j] = m_adj[i][j]; //start with conn == adj matrix
}
}
for(int im = 0; im < m_size; ++ im){ //intermediate points --> transitive closure
for(int source = 0; source < m_size; ++source){ //source = starting point
for(int sink = 0; sink <m_size; ++sink){ //sink = ending point
if(source == sink){
continue;
}else if(m_conn[source][im] != std::numeric_limits<double>::max() &&
m_conn[im][sink] != std::numeric_limits<double>::max() &&
m_conn[source][sink] > m_conn[source][im] + m_conn[im][sink]){
m_conn[source][sink] = m_conn[source][im] + m_conn[im][sink];
}
}
}
}
}
//gets the cheapest weight that there is
double WGraph::cheapestCost(VertexID i, VertexID j){
return m_conn[i][j]; //constant
}
//calculates the minimum spanning tree
void WGraph::computeMST() {
//keeps track of how many edges there are
int numEdges = 0;
double minCost = 0.0;
int vertexSum;
//creating a vertex that allows for the amount of nodes to be inserted for union later on
int *vertex = new int[m_size];
//populating the vertex
for (int i = 0; i < m_size; i++) {
vertex[i] = i;
vertexSum += vertex[i];
}
//initiating the newCons matrix
//populating the newCons matrix with 0.0 so that later down on the road that 0.0 can be replaced with some other weight
this->newCons = new double *[m_size];
for (int i = 0; i < m_size; i++) {
this->newCons[i] = new double[m_size];
for (int j = 0; j < m_size; j++) {
this->newCons[i][j] = 0.0;
}
}
//creating a queue that hold the position class
PQueue<position *> *PQ = new PQueue<position *>(true);
for (int i = 0; i < m_size; i++) {
for (int j = 0; j < m_size; j++) {
double weight = this->m_adj[i][j];
if (weight != 0.0) {
//creates a position instance
//hold the row and col number and the weight at that specific location
position *pos = new position(i, j, weight);
//add that position to the queue
PQ->add(pos);
}
}
}
//while the priority queue is not empty the position at the top will be removed and return it's contents
while (!PQ->isEmpty() && numEdges <= m_size) {
//position is set to which ever position was at the top
position *newPos = PQ->removeTop();
double weighted = newPos->getWeight();
int rowX = newPos->getRow();
int colY = newPos->getCol();
cout << setprecision(2) << fixed;
cout << "Weight: " << weighted << " at (" << rowX << ", " << colY << ")" << endl;
//this is where the unification process starts
//if the row location is not equal to the column location on the vertex
//then the vertex is switched
if (vertex[rowX] != vertex[colY]) {
for (int i = 0; i < m_size; i++) {
if (vertex[i] == colY) {
vertex[i] = vertex[rowX];
}
}
this->newCons[rowX][colY] = weighted;
this->newCons[colY][rowX] = weighted;
numEdges +=1;
}
}
//now calculates the minimum cost by traversing through the newCons matrix and adding it to the minCost variable
for (int i = 0; i < m_size; i++) {
for (int j = 0; j < m_size; j++) {
minCost += this->newCons[i][j];
}
}
//minCost is divided here due to the fact that the matrix is symmetrical, so it is double of what it has to be
minCost /= 2.0;
//prints the newCons matrix with all the connections that are connected through Kruskal's method.
cout << endl;
cout << "Kruskal Adjacency Matrix" << endl;
for (int i = 0; i < m_size; i++) {
for (int j = 0; j < m_size; j++) {
//set precision to 2 to make minCost cout to look better
cout << setprecision(2) << fixed;
cout << this->newCons[i][j] << " ";
}
cout << endl;
}
cout << "Min cost: " << minCost << endl;
}