-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathprim.c
161 lines (141 loc) · 3.18 KB
/
prim.c
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
/* Source
* Implementation of Prim's algorithm
* September 2nd, 2017
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <assert.h>
#include "graph_input.h"
#define INFINITY 0xFFFF
int N, M, directed, weighted;
int * edge_matrix;
char ** node_list;
int * previous;
int * distances;
void Prim(int sourcenode);
int * newPriorityQueueFromEdgeMatrix(int sourcenode);
void changeDistance(int key, int newDistance);
int extractNodeOfMinDistanceToMST(void);
bool allNodesVisited(void);
void printOptimalPaths(int curr_node);
bool validNeighbour(int i, int j);
int main (void)
{
printf("\nWelcome to prim.c!\n");
getParameters(&N, &M, &directed, &weighted);
if (directed)
{
printf("Prim's algorithm cannot be run on a directed graph.\n");
return 1;
}
node_list = getNodeList(N);
assert(node_list);
bool negativeEdgesOkay = true;
edge_matrix = getGraph(N, M, directed, weighted, node_list, negativeEdgesOkay);
assert(edge_matrix);
int sourcenode = getSourceNode(N, node_list);
Prim(sourcenode);
deleteGraph(N, edge_matrix, node_list);
return 0;
}
void Prim(int sourcenode)
{
distances = newPriorityQueueFromEdgeMatrix(sourcenode); // Sets source distance to 0 and rest to infinity
assert(distances);
previous = malloc(N * sizeof(int));
assert(previous);
for (int i = 0; i < N; i++)
{
previous[i] = (i == sourcenode) ? sourcenode : -1; // Previous node in optimal path undefined
}
while(!allNodesVisited())
{
int nextNode = extractNodeOfMinDistanceToMST();
for (int j = 0; j < N; j++)
{
if (validNeighbour(nextNode, j))
{
int newPathLength = edge_matrix[nextNode*N + j];
if (newPathLength < distances[j])
{
changeDistance(j, newPathLength);
previous[j] = nextNode;
}
}
}
}
printf("Printing optimal paths:\n");
for(int i = 0; i < N; i++)
{
printOptimalPaths(i);
printf("\n");
}
free(distances);
free(previous);
}
bool validNeighbour(int i, int j)
{
bool valid = true;
if (!edgeExists(i, j, N, edge_matrix))
{
valid = false;
}
if (distances[j] == -1) // already visited node
{
valid = false;
}
return valid;
}
int * newPriorityQueueFromEdgeMatrix(int sourcenode)
{
int * p_queue = malloc(N * sizeof(int));
assert(p_queue);
for (int i = 0; i < N; i++)
{
p_queue[i] = (i == sourcenode) ? 0 : INFINITY;
}
return p_queue;
}
void changeDistance(int key, int newDistance)
{
assert(key < N);
assert(newDistance < INFINITY);
distances[key] = newDistance;
}
int extractNodeOfMinDistanceToMST(void)
{
int i;
int min = INFINITY;
int min_index = -1; // returns -1 if distances is empty
for (i = 0; i < N; i++)
{
if (distances[i] != -1 && distances[i] <= min)
{
min = distances[i];
min_index = i;
}
}
distances[min_index] = -1;
return min_index;
}
bool allNodesVisited(void)
{
for (int i = 0; i < N; i++)
{
if (distances[i] != -1)
{
return false;
}
}
return true;
}
void printOptimalPaths(int curr_node)
{
printf("%s", node_list[curr_node]);
if (previous[curr_node] != curr_node)
{
printf(" -- ");
printOptimalPaths(previous[curr_node]);
}
}