In this code I want to make Kruskal's algorithm, which calculates a minimum spanning tree of a given graph. And I want to use min-heap and disjoint set at the code.
To make time complexity of O(e log n), where e is the number of edges and n is the number of vertices in the graph, I will use heap and disjoint set trees.
So the method I went with was:
- Check the numbers of vertices and edges in the given input file and make parent array and struct edge which can include at most
10000vertices and50000000edges. - Sort the edges by the weight in a min heap in descending order.
- Take out edges from min heap one by one and check whether it makes cycle until min heap is empty
- If the number of edges selected is
vertices-1(if all vertices already connected ) break the while loop and print each edges and sum of weights. If all vertices can make minimum spanning tree it prints connected and if all vertices can not make minimum spanning tree it prints disconnected.
I thought the code is well done but when I run this in putty, it is exiting with segmentation fault (core dumped)
input (example)
7
9
0 1 28
0 5 10
1 2 16
1 6 14
2 3 12
3 4 22
3 6 18
4 5 25
4 6 24
result(I want)
0 5 10
2 3 12
1 6 14
1 2 16
3 4 22
4 5 25
99
CONNECTED
I checked the edges are well stored in min-heap in descending order. But I think it has mistakes in making minimum spanning tree. These are points that I am suspicious in the code.
- Should I make
edge minheapby dynamic allocation instead ofminheap[50000000]? - Should I make additional data structures apart from the array
parentandstruct edge.
It is the code I made! Can you give me help or advice ?
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<time.h>
#define maxvertice 10000
#define maxedge 50000000
typedef struct edge { //structure to store vertices and weight
int a, b;
int w;
}
edge;
int n = 0; //numbers of edge in the minheap
int parent[maxvertice] = {-1,};
//array to represent disjoint sets! parent which stores the vertice connected
//if it is not connected(independent) it's parent is -1
edge minheap[maxedge]; //heap that sorts edges
void insertheap(edge item, int * n); // arrange edges by the weight in descending order
edge deleteheap(int * n); //popping out from the root (in descending order)
void makeunion(int x, int y); // this make x and y combined
int findparent(int i);
int main(int argc, char * argv[]) {
double start, end;
int i, nv, ne, sumofweight = 0, isitdone;
int cnt_edge = 0;
edge item;
//////////////
if (argc != 2) {
printf("usage: ./hw3 input_filename\n");
return 0;
}
FILE * fp = fopen(argv[1], "r");
if (fp == NULL) {
printf("The input file does not exist.\n");
return 0;
}
FILE * result = fopen("hw3_result.txt", "w");
start = (double) clock() / CLOCKS_PER_SEC;
fscanf(fp, "%d", & nv);
printf("to test : number of vertices : %d\n", nv);
fscanf(fp, "%d", & ne);
printf("to test : number of edges : %d\n", ne);
for (i = 0; i < ne; i++) {
int firstv, secondv, weight;
edge newedge;
fscanf(fp, "%d %d %d", & firstv, & secondv, & weight);
newedge.a = firstv;
newedge.b = secondv;
newedge.w = weight;
// get vertices and edge's weight from the input file and put in heap
insertheap(newedge, & n);
}
/*
for(i =0 ; i<ne; i++){
item= deleteheap(&n);
printf("%d", item.w);
}*/
while (minheap != NULL) { //pop out from the heap until mst is completed
item = deleteheap( & n);
//union at array parent
int par1, par2;
par1 = findparent(item.a);
par2 = findparent(item.b);
if (par1 != par2) {
makeunion(par1, par2);
printf("%d %d %d\n", item.a, item.b, item.w);
cnt_edge = cnt_edge + 1;
sumofweight += item.w;
}
if (cnt_edge == nv - 1) break;
}
if (cnt_edge == nv - 1) {
// fprintf(result, "CONNECTED");
printf("%d\n", sumofweight);
printf("CONNECTED");
}
if (cnt_edge < nv - 1) {
// fprintf(result, "DISCONNECTED");
printf("DISCONNECTED\n");
}
end = (((double) clock()) / CLOCKS_PER_SEC);
fclose(fp);
fclose(result);
printf("output written to hw3_result.txt.\n");
printf("running time: %1f", (end - start));
printf(" seconds\n");
}
void makeunion(int x, int y) {
parent[x] = y;
}
int findparent(int i) {
for (; parent[i] >= 0; i = parent[i]);
return i;
}
void insertheap(edge item, int * n) {
int i;
i = * n;
++( * n);
while ((i != 0) && (item.w < minheap[i / 2].w)) {
minheap[i] = minheap[i / 2];
i /= 2;
}
minheap[i] = item;
printf("to test : the wieght %d is inserted in :%d \n", item.w, i);
}
edge deleteheap(int * n) {
int parent, child;
parent = 0;
child = 1;
edge item, temp;
item = minheap[0];
temp = minheap[( * n) - 1];
( * n) --;
while (child <= * n) {
if ((child < * n) && (minheap[child].w > minheap[child + 1].w)) child++;
if (temp.w <= minheap[child].w) break;
minheap[parent] = minheap[child];
parent = child;
child *= 2;
}
minheap[parent] = temp;
return item;
}
while (minheap!=NULL)is wrong, it can never hit that becauseminheapis not a pointer. Looking at your code, it might bewhile (n>0).