Kruskal's algorithm - cpp graph program

Hi :)
I'm trying to figure out where should I change this code to get the valid answer for MST graph.
This code is not completely mine, but I really need to understand it fully.

The graph in the example below in the code could be represented like this:

https://ibb.co/Mp128bk

The problem is, the MST function is not working fully correct - the output is graph with violet edge, which is wrong. It should be the green edge with minimum sum 63, not 68, as follows with the violet one.

https://ibb.co/42Lv15t // I'm sorry for links but I do not know how to put them on this site

What could cause this mistake?

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
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>

using namespace std;

// a structure to represent a weighted edge in graph
struct Edge
{
    int src, dest, weight;
};

// a structure to represent a connected, undirected and weighted graph
struct Graph
{
        // V-> Number of vertices, E-> Number of edges
        int V, E;

        struct Edge* edge;
};

// Creates a graph with V vertices and E edges
struct Graph* createGraph(int V, int E)
{
    struct Graph* graph = (struct Graph*) malloc(sizeof(struct Graph));
    graph->V = V;
    graph->E = E;

    graph->edge = (struct Edge*) malloc(graph->E * sizeof(struct Edge));

    return graph;
}

// A structure to represent a subset for union-find
struct subset
{
        int parent;
        int rank;
};

// A utility function to find set of an element i
// (uses path compression technique)
int find(struct subset subsets[], int i)
{
    // find root and make root as parent of i (path compression)
    if (subsets[i].parent != i)
        subsets[i].parent = find(subsets, subsets[i].parent);

    return subsets[i].parent;
}

// A function that does union of two sets of x and y
// (uses union by rank)
void Union(struct subset subsets[], int x, int y)
{
    int xroot = find(subsets, x);
    int yroot = find(subsets, y);

    // Attach smaller rank tree under root of high rank tree
    // (Union by Rank)
    if (subsets[xroot].rank < subsets[yroot].rank)
        subsets[xroot].parent = yroot;
    else if (subsets[xroot].rank > subsets[yroot].rank)
        subsets[yroot].parent = xroot;

    // If ranks are same, then make one as root and increment
    // its rank by one
    else
    {
        subsets[yroot].parent = xroot;
        subsets[xroot].rank++;
    }
}

// Compare two edges according to their weights.
// Used in qsort() for sorting an array of edges
int myComp(const void* a, const void* b)
{
    struct Edge* a1 = (struct Edge*) a;
    struct Edge* b1 = (struct Edge*) b;
    return a1->weight > b1->weight;
}

// The main function to construct MST using Kruskal's algorithm
void KruskalMST(struct Graph* graph)
{
    int V = graph->V;
    struct Edge result[V]; // Tnis will store the resultant MST
    int e = 0; // An index variable, used for result[]
    int i = 0; // An index variable, used for sorted edges

    // Step 1:  Sort all the edges in non-decreasing order of their weight
    // If we are not allowed to change the given graph, we can create a copy of
    // array of edges
    qsort(graph->edge, graph->E, sizeof(graph->edge[0]), myComp);

    // Allocate memory for creating V ssubsets
    struct subset *subsets = (struct subset*) malloc(V * sizeof(struct subset));

    // Create V subsets with single elements
    for (int v = 0; v < V; ++v)
    {
        subsets[v].parent = v;
        subsets[v].rank = 0;
    }

    // Number of edges to be taken is equal to V-1
    while (e < V - 1)
    {
        // Step 2: Pick the smallest edge. And increment the index
        // for next iteration
        struct Edge next_edge = graph->edge[i++];

        int x = find(subsets, next_edge.src);
        int y = find(subsets, next_edge.dest);

        // If including this edge does't cause cycle, include it
        // in result and increment the index of result for next edge
        if (x != y)
        {
            result[e++] = next_edge;
            Union(subsets, x, y);
        }
        // Else discard the next_edge
    }

    cout<<"Following are the edges in the constructed MST" << endl;
    for (i = 0; i < e; ++i)
        cout << result[i].src << " -- " << result[i].dest << " == " << result[i].weight << endl;
    return;
}

int main()
{
    int V = 9; // Number of vertices in graph
    int E = 15; // Number of edges in graph
    struct Graph* graph = createGraph(V, E);

    // add edge 0-1
    graph->edge[0].src = 0;
    graph->edge[0].dest = 1;
    graph->edge[0].weight = 3;

    // add edge 0-2
    graph->edge[1].src = 0;
    graph->edge[1].dest = 2;
    graph->edge[1].weight = 12;

    // add edge 0-3
    graph->edge[2].src = 0;
    graph->edge[2].dest = 3;
    graph->edge[2].weight = 26;

    // add edge 1-4
    graph->edge[3].src = 1;
    graph->edge[3].dest = 4;
    graph->edge[3].weight = 10;

    // add edge 2-3
    graph->edge[5].src = 2;
    graph->edge[5].dest = 3;
    graph->edge[5].weight = 17;

    // add edge 2-4
    graph->edge[4].src = 2;
    graph->edge[4].dest = 4;
    graph->edge[4].weight = 7;


    // add edge 2-5
    graph->edge[6].src = 2;
    graph->edge[6].dest = 5;
    graph->edge[6].weight = 15;

    // add edge 3-5
    graph->edge[7].src = 3;
    graph->edge[7].dest = 5;
    graph->edge[7].weight = 13;

    // add edge 3-6
    graph->edge[8].src = 3;
    graph->edge[8].dest = 6;
    graph->edge[8].weight = 14;

    // add edge 4-5
    graph->edge[9].src = 4;
    graph->edge[9].dest = 5;
    graph->edge[9].weight = 8;

    // add edge 4-7
    graph->edge[10].src = 4;
    graph->edge[10].dest = 7;
    graph->edge[10].weight = 4;

    // add edge 5-6
    graph->edge[11].src = 5;
    graph->edge[11].dest = 6;
    graph->edge[11].weight = 9;

    // add edge 5-7
    graph->edge[12].src = 5;
    graph->edge[12].dest = 7;
    graph->edge[12].weight = 6;

    // add edge 6-7
    graph->edge[14].src = 6;
    graph->edge[14].dest = 7;
    graph->edge[14].weight = 16;

    // add edge 6-8
    graph->edge[13].src = 6;
    graph->edge[13].dest = 8;
    graph->edge[13].weight = 11;

    KruskalMST(graph);

    return 0;
}
Last edited on
I’ll post back later with help. (Unless someone beats me too it.)

First glance: check your qsort comparison function.
So, I just got a chance to look at it. All I did was repair your comparitor and it works fine.

Always remember to check the documentation when you are using functions. I swear I’ve got stuff memorized because I look at it so much.

The qsort() comparitor function returns one of three values:

    •  < 0  :  a < b
    • == 0 : a == b
    •  > 0  :  a > b

People often do this with a simple subtraction (which is what I think was intended when it was designed), but that has corner cases people forget. Do it properly:

78
79
80
81
82
83
84
85
86
87
// Compare two edges according to their weights.
// Used in qsort() for sorting an array of edges
int myComp(const void* a, const void* b)
{
    struct Edge* a1 = (struct Edge*) a;
    struct Edge* b1 = (struct Edge*) b;
    if (a1->weight < b1->weight) return -1;
    if (a1->weight > b1->weight) return  1;
    return 0;
}

After that the MST is properly generated.

Hope this helps.
Hey Duthomhas, you helped me with this... thanks a lot.
As you predicted, I haven't looked into the qsort documentation - that was it, now it works perfectly. Thanks again!
Topic archived. No new replies allowed.