Skip to content

Commit 24afd87

Browse files
authored
Merge pull request #13 from rdrahul/master
kruskals Added #3
2 parents 0e5230f + f00d068 commit 24afd87

File tree

3 files changed

+279
-0
lines changed

3 files changed

+279
-0
lines changed

graph/kruskals/Readme.md

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
# Kruskal Algorithm for Minimum Spanning Tree
2+
3+
A Minimum Spanning Tree is a tree that include all the vertex of a graph such that the total sum of all the edges are minimized. Kruskal alogorithm suggest a greedy approach for this, We sorts all the edges in non decreasing way and keep selecting the minimum edges and adding it to our MST. When we add an Edge to existing MST it should not form a cycle.
4+
5+
Let's look at it with example.
6+
Suppose we have a graph as described below
7+
```
8+
9+
0 -------[4]----------- 1 -----[8]------ 2
10+
| |
11+
| |
12+
[8] -- [7] -------- 5 ------[2]-----|
13+
| / |
14+
| / [6]
15+
| / |
16+
3 ------[1]-------- 4 ---|
17+
```
18+
19+
it can be summarized as
20+
```
21+
Vertex From Vertex To Weight
22+
0 1 4
23+
0 3 8
24+
1 2 8
25+
2 5 2
26+
3 4 1
27+
4 5 6
28+
5 3 7
29+
30+
```
31+
32+
Our Aim is to find the Minimum Spanning Tree From this Graph.
33+
First we will Sort the Edges in a non decreasing order. After sorting in non decreasing order we would have following order of edges.
34+
```
35+
Vertex From Vertex To Weight
36+
3 4 1
37+
2 5 2
38+
0 1 4
39+
4 5 6
40+
5 3 7
41+
0 3 8
42+
1 2 8
43+
44+
```
45+
Now we will Select the minimum edges one by one try to add it to the MST if it does not form a cycle
46+
then we will add it to the MST else we will skip that edge.
47+
48+
The first edge we select is
49+
```
50+
51+
3-------[1]-------- 4
52+
53+
current MST. total weight 1
54+
```
55+
56+
Then we move to next minimum edge. Similarly If we keep repeating at some point after adding 4 edges we will have our MST like this
57+
```
58+
0 -------[4]----------- 1 2
59+
|
60+
|
61+
5 ------[2]-----|
62+
|
63+
[6]
64+
|
65+
3 ------[1]-------- 4 ---|
66+
```
67+
68+
now the next minim edge is 5-3 with weight 7 but addding it will make a cycle so we will skip this edge. We will then try to add the edge 0-3 [weight=8]
69+
70+
```
71+
0 -------[4]----------- 1 -----[8]------ 2
72+
|
73+
|
74+
5 ------[2]-----|
75+
|
76+
[6]
77+
|
78+
3 ------[1]-------- 4 ---|
79+
80+
Total Weight : 21
81+
```
82+
Thus we have obtained out Minimum Spanning Tree.
83+
84+
85+
86+
# Algorithm
87+
88+
The algorithm for kruskal works following way
89+
1. Sort all the edges in non-decreasing order of their weight.
90+
2. Pick the smallest edge. Check if it forms a cycle with the spanning tree formed so far. If cycle is not formed, include this edge. Else, discard it.
91+
3. Repeat step#2 until there are (V-1) edges in the spanning tree.
92+

graph/kruskals/kruskals.go

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
package graph
2+
3+
import (
4+
"fmt"
5+
"sort"
6+
)
7+
8+
//======================================== Graph Structure Implementation starts========================================//
9+
10+
//Edge => an edge struct which represent a edge from vertex A to vertex B having X Weight
11+
type Edge struct {
12+
From int
13+
To int
14+
Weight int
15+
}
16+
17+
//Graph => graph data structure
18+
type Graph struct {
19+
vertices int
20+
edges [][]Edge
21+
}
22+
23+
//Initialize => initializes the graph
24+
func (g *Graph) Initialize(vertices int) {
25+
26+
//set the vertices we have
27+
g.vertices = vertices
28+
29+
// initialize the vertices
30+
if g.edges == nil {
31+
g.edges = make([][]Edge, vertices)
32+
}
33+
34+
//initialize each vertex as an empty array
35+
for i := 0; i < vertices; i++ {
36+
g.edges[i] = []Edge{}
37+
}
38+
}
39+
40+
//AddEdge => weighted edge add
41+
func (g *Graph) AddEdge(u int, v int, w int) {
42+
currEdge := Edge{u, v, w}
43+
44+
//for undirected graph both should have the entry
45+
currEdgeU := Edge{v, u, w}
46+
47+
//set the v is reachabe from u
48+
g.edges[u] = append(g.edges[u], currEdge)
49+
g.edges[v] = append(g.edges[v], currEdgeU)
50+
51+
}
52+
53+
//Print the graph to see the Adjacency List
54+
func (g *Graph) Print() {
55+
56+
for i := range g.edges {
57+
fmt.Printf("%v\n", g.edges[i])
58+
}
59+
60+
}
61+
62+
//========================================= Graph Implementation Ends Here =======================================//
63+
64+
/*
65+
# A utility function to find set of an element i
66+
67+
68+
# A function that does union of two sets of x and y
69+
# (uses union by rank)
70+
def union(self, parent, rank, x, y):
71+
xroot = self.find(parent, x)
72+
yroot = self.find(parent, y)
73+
74+
# Attach smaller rank tree under root of
75+
# high rank tree (Union by Rank)
76+
if rank[xroot] < rank[yroot]:
77+
parent[xroot] = yroot
78+
elif rank[xroot] > rank[yroot]:
79+
parent[yroot] = xroot
80+
81+
# If ranks are same, then make one as root
82+
# and increment its rank by one
83+
else :
84+
parent[yroot] = xroot
85+
rank[xroot] += 1
86+
*/
87+
88+
//traverses the parents array and fetches the representative parent of the vertex x
89+
func findParent(parent []int, i int) int {
90+
if parent[i] == i {
91+
return i
92+
}
93+
return findParent(parent, parent[i])
94+
}
95+
96+
//Merges two vertices and sets the parent by rank
97+
func union(parent []int, rank []int, x int, y int) {
98+
xroot := findParent(parent, x)
99+
yroot := findParent(parent, y)
100+
101+
if rank[x] > rank[y] {
102+
parent[yroot] = xroot
103+
} else if rank[x] < rank[y] {
104+
parent[xroot] = yroot
105+
} else {
106+
parent[yroot] = xroot
107+
rank[xroot] = 1
108+
}
109+
}
110+
111+
// Kruskals algorithm
112+
func Kruskals(g Graph) {
113+
114+
//get all the edges in an array and then sort it
115+
sortedEdges := []Edge{}
116+
MST := []Edge{}
117+
118+
//TODO : Use a min Heap to optimize the following
119+
for i := range g.edges {
120+
for edge := range g.edges[i] {
121+
sortedEdges = append(sortedEdges, g.edges[i][edge])
122+
}
123+
}
124+
125+
sort.Slice(sortedEdges, func(i, j int) bool {
126+
return sortedEdges[i].Weight < sortedEdges[j].Weight
127+
})
128+
129+
//initialize parent and the rank
130+
parent := make([]int, g.vertices)
131+
rank := make([]int, g.vertices)
132+
133+
for i := 0; i < g.vertices; i++ {
134+
parent[i] = i
135+
rank[i] = 0
136+
}
137+
138+
i := 0
139+
e := 0
140+
141+
//we need to select V-1 edges for all the edges to connect
142+
for e < g.vertices-1 {
143+
144+
//select the minumum edge not choosen yet
145+
currEdge := sortedEdges[i]
146+
i++
147+
148+
//find the parent of the vertices of current edge
149+
x := findParent(parent, currEdge.From)
150+
y := findParent(parent, currEdge.To)
151+
152+
//if parent of x is not equal to parent of y means both have different sets and thus wont form a cycle when merged
153+
//so we select this edge and increase the edges count
154+
if x != y {
155+
e++
156+
//add it to mst
157+
MST = append(MST, currEdge)
158+
//since the vertices are now connected union both of them for future use.
159+
union(parent, rank, x, y)
160+
}
161+
162+
}
163+
fmt.Println("PRINTING THE MST")
164+
fmt.Println(MST)
165+
166+
}

graph/kruskals/kruskals_test.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package graph
2+
3+
import (
4+
"testing"
5+
)
6+
7+
func TestGraph(t *testing.T) {
8+
var graph = Graph{}
9+
graph.Initialize(6)
10+
graph.AddEdge(0, 1, 4)
11+
graph.AddEdge(0, 3, 8)
12+
graph.AddEdge(3, 4, 1)
13+
graph.AddEdge(3, 5, 7)
14+
graph.AddEdge(4, 5, 6)
15+
graph.AddEdge(2, 5, 2)
16+
graph.AddEdge(1, 3, 11)
17+
graph.AddEdge(1, 2, 8)
18+
graph.Print()
19+
Kruskals(graph)
20+
21+
}

0 commit comments

Comments
 (0)