I have written some basic implementation of a Minimum Spanning Tree using a indexed minimum priority queue. For the implementation of the Priority Queue I used Sedgewick's Tutorials.
However, it seems that I am passing a lot of arrays around for the priority queue. Here, is my code snippet. Could someone point out the obvious faults and also suggest a better abstraction for the priority queue. (Since Sedgewick's Tutorials were in Java, I translated them to C and I think that my implementation is not good.)
void minimum_spanning_tree(adj_list *adjacency_list)
{
int pq[NMAX + 1];
float keys[NMAX];
int size_of_heap = 0;
float node_key[NMAX];
int node_parent[NMAX];
boolean marked[NMAX] = { FALSE };
for (int i = 0; i < adjacency_list->no_vert; i++) {
node_key[i] = INT_MAX;
node_parent[i] = -1;
insert(i, &size_of_heap, node_key[i], pq, keys);
}
int start_vertex = 0;
node_key[start_vertex] = 0.0;
node_parent[start_vertex] = 0;
decrease_key(start_vertex, &size_of_heap, node_key[start_vertex], pq, keys);
while (size_of_heap > 0) {
int vertex = delete_min(&size_of_heap, pq, keys);
marked[vertex] = TRUE; // Why marked? Because once an element is deleted
// from a queue it is marked i.e. is already included.
bag *bag_of_vertex = adjacency_list->bags[vertex];
node *node_of_vertex = bag_of_vertex->first;
while (node_of_vertex != NULL) {
relax_min_span_tree(node_of_vertex, node_key, node_parent, &size_of_heap, pq, keys, marked);
node_of_vertex = node_of_vertex->next;
}
}
// create_minimum_span_tree(start_vertex, adjacency_list, node_key, node_parent);
create_minimum_span_tree_queue(adjacency_list, node_key, node_parent);
}
void relax_min_span_tree(node *node_of_vertex, float node_key[], int node_parent[], int *size_of_heap, int pq[], float keys[], boolean marked[])
{
int from, to;
from = node_of_vertex->from;
to = node_of_vertex->to;
if (marked[to] == TRUE)
return;
if (node_of_vertex->weight < node_key[to]) {
node_key[to] = node_of_vertex->weight;
node_parent[to] = from;
decrease_key(to, size_of_heap, node_key[to], pq, keys);
}
}
void create_minimum_span_tree_queue(adj_list *adjacency_list, float node_key[], int node_parent[])
{
queue *queue_inst = queue_create();
for (int i = 0; i < adjacency_list->no_vert; i++) {
edge *edge_inst = (edge *) malloc(sizeof(edge));
edge_inst->from = node_parent[i];
edge_inst->to = i;
edge_inst->weight = node_key[i];
queue_add(queue_inst, edge_inst);
}
fprintf(stdout, "The minimum spanning tree: \n");
while (!queue_is_empty(queue_inst)) {
edge *edge_inst = queue_remove(queue_inst);
fprintf(stdout, "%2d ->%2d == %.2f\n", edge_inst->from, edge_inst->to, edge_inst->weight);
free(edge_inst);
}
queue_destroy(queue_inst);
}
The Indexed Minimum Priority Queue implementation -
boolean insert(int i, int *size, float key, int pq[], float keys[])
{
if (i < 0 || i > NMAX) return FALSE;
(*size)++;
pq[*size] = i;
keys[i] = key;
// swim(size, pq, keys);
swim_simple(*size, pq, keys);
return TRUE;
}
boolean greater(int i, int j, int pq[], float keys[])
{
if (keys[pq[i]] > keys[pq[j]]) return TRUE;
else return FALSE;
}
void exch(int i, int j, int pq[])
{
int swap = pq[i];
pq[i] = pq[j];
pq[j] = swap;
}
void swim_simple(int k, int pq[], float keys[])
{
if (k == 1) return;
while (k > 1 && greater(k/2, k, pq, keys)) {
exch(k, k/2, pq);
k = k/2;
}
}
int delete_min(int *size, int pq[], float keys[])
{
if ((*size) <= 0) {
return INT_MAX;
}
int min = pq[1];
exch(1, (*size)--, pq);
sink(1, size, pq, keys);
return min;
}
void sink(int k, int *size, int pq[], float keys[])
{
while (2 * k <= (*size)) {
int j = 2 * k;
if (j < (*size) && greater(j, j+1, pq, keys)) j++;
if (!greater(k, j, pq, keys)) break;
exch(k, j, pq);
k = j;
}
}
The decrease key method -
boolean decrease_key(int i, int *size, float key, int pq[], float keys[])
{
if (i < 0 || i > NMAX) return FALSE;
keys[i] = key;
swim(i, pq, keys); // swim(pq[i], pq, keys) also works, no idea why.
return TRUE;
}
index
basedminimum priority queue
. Also I insert all the elements at the beginning itself withINT_MAX
. So when akey
is changed (i.e. the edge weight is changed) I decrease thekey
belonging to a particular ID. (I forgot to include that in the code above. I have added it now.) – yadav_vi Dec 4 '14 at 9:10swim
here meanswim_simple
or is there a separateswim
function? – JS1 Dec 4 '14 at 9:40swim
implementation was a more complex to understand so I tried simplifying it. My entire project is hosted at GitHub. – yadav_vi Dec 4 '14 at 9:45