Skip to content

Commit

Permalink
kruskals Added ektagarg#3
Browse files Browse the repository at this point in the history
  • Loading branch information
Rahul Dwivedi authored and Rahul Dwivedi committed Oct 30, 2019
1 parent 8e08415 commit f00d068
Show file tree
Hide file tree
Showing 3 changed files with 279 additions and 0 deletions.
92 changes: 92 additions & 0 deletions graph/kruskals/Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# Kruskal Algorithm for Minimum Spanning Tree

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.

Let's look at it with example.
Suppose we have a graph as described below
```
0 -------[4]----------- 1 -----[8]------ 2
| |
| |
[8] -- [7] -------- 5 ------[2]-----|
| / |
| / [6]
| / |
3 ------[1]-------- 4 ---|
```

it can be summarized as
```
Vertex From Vertex To Weight
0 1 4
0 3 8
1 2 8
2 5 2
3 4 1
4 5 6
5 3 7
```

Our Aim is to find the Minimum Spanning Tree From this Graph.
First we will Sort the Edges in a non decreasing order. After sorting in non decreasing order we would have following order of edges.
```
Vertex From Vertex To Weight
3 4 1
2 5 2
0 1 4
4 5 6
5 3 7
0 3 8
1 2 8
```
Now we will Select the minimum edges one by one try to add it to the MST if it does not form a cycle
then we will add it to the MST else we will skip that edge.

The first edge we select is
```
3-------[1]-------- 4
current MST. total weight 1
```

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
```
0 -------[4]----------- 1 2
|
|
5 ------[2]-----|
|
[6]
|
3 ------[1]-------- 4 ---|
```

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]

```
0 -------[4]----------- 1 -----[8]------ 2
|
|
5 ------[2]-----|
|
[6]
|
3 ------[1]-------- 4 ---|
Total Weight : 21
```
Thus we have obtained out Minimum Spanning Tree.



# Algorithm

The algorithm for kruskal works following way
1. Sort all the edges in non-decreasing order of their weight.
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.
3. Repeat step#2 until there are (V-1) edges in the spanning tree.

166 changes: 166 additions & 0 deletions graph/kruskals/kruskals.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
package graph

import (
"fmt"
"sort"
)

//======================================== Graph Structure Implementation starts========================================//

//Edge => an edge struct which represent a edge from vertex A to vertex B having X Weight
type Edge struct {
From int
To int
Weight int
}

//Graph => graph data structure
type Graph struct {
vertices int
edges [][]Edge
}

//Initialize => initializes the graph
func (g *Graph) Initialize(vertices int) {

//set the vertices we have
g.vertices = vertices

// initialize the vertices
if g.edges == nil {
g.edges = make([][]Edge, vertices)
}

//initialize each vertex as an empty array
for i := 0; i < vertices; i++ {
g.edges[i] = []Edge{}
}
}

//AddEdge => weighted edge add
func (g *Graph) AddEdge(u int, v int, w int) {
currEdge := Edge{u, v, w}

//for undirected graph both should have the entry
currEdgeU := Edge{v, u, w}

//set the v is reachabe from u
g.edges[u] = append(g.edges[u], currEdge)
g.edges[v] = append(g.edges[v], currEdgeU)

}

//Print the graph to see the Adjacency List
func (g *Graph) Print() {

for i := range g.edges {
fmt.Printf("%v\n", g.edges[i])
}

}

//========================================= Graph Implementation Ends Here =======================================//

/*
# A utility function to find set of an element i
# A function that does union of two sets of x and y
# (uses union by rank)
def union(self, parent, rank, x, y):
xroot = self.find(parent, x)
yroot = self.find(parent, y)
# Attach smaller rank tree under root of
# high rank tree (Union by Rank)
if rank[xroot] < rank[yroot]:
parent[xroot] = yroot
elif rank[xroot] > rank[yroot]:
parent[yroot] = xroot
# If ranks are same, then make one as root
# and increment its rank by one
else :
parent[yroot] = xroot
rank[xroot] += 1
*/

//traverses the parents array and fetches the representative parent of the vertex x
func findParent(parent []int, i int) int {
if parent[i] == i {
return i
}
return findParent(parent, parent[i])
}

//Merges two vertices and sets the parent by rank
func union(parent []int, rank []int, x int, y int) {
xroot := findParent(parent, x)
yroot := findParent(parent, y)

if rank[x] > rank[y] {
parent[yroot] = xroot
} else if rank[x] < rank[y] {
parent[xroot] = yroot
} else {
parent[yroot] = xroot
rank[xroot] = 1
}
}

// Kruskals algorithm
func Kruskals(g Graph) {

//get all the edges in an array and then sort it
sortedEdges := []Edge{}
MST := []Edge{}

//TODO : Use a min Heap to optimize the following
for i := range g.edges {
for edge := range g.edges[i] {
sortedEdges = append(sortedEdges, g.edges[i][edge])
}
}

sort.Slice(sortedEdges, func(i, j int) bool {
return sortedEdges[i].Weight < sortedEdges[j].Weight
})

//initialize parent and the rank
parent := make([]int, g.vertices)
rank := make([]int, g.vertices)

for i := 0; i < g.vertices; i++ {
parent[i] = i
rank[i] = 0
}

i := 0
e := 0

//we need to select V-1 edges for all the edges to connect
for e < g.vertices-1 {

//select the minumum edge not choosen yet
currEdge := sortedEdges[i]
i++

//find the parent of the vertices of current edge
x := findParent(parent, currEdge.From)
y := findParent(parent, currEdge.To)

//if parent of x is not equal to parent of y means both have different sets and thus wont form a cycle when merged
//so we select this edge and increase the edges count
if x != y {
e++
//add it to mst
MST = append(MST, currEdge)
//since the vertices are now connected union both of them for future use.
union(parent, rank, x, y)
}

}
fmt.Println("PRINTING THE MST")
fmt.Println(MST)

}
21 changes: 21 additions & 0 deletions graph/kruskals/kruskals_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package graph

import (
"testing"
)

func TestGraph(t *testing.T) {
var graph = Graph{}
graph.Initialize(6)
graph.AddEdge(0, 1, 4)
graph.AddEdge(0, 3, 8)
graph.AddEdge(3, 4, 1)
graph.AddEdge(3, 5, 7)
graph.AddEdge(4, 5, 6)
graph.AddEdge(2, 5, 2)
graph.AddEdge(1, 3, 11)
graph.AddEdge(1, 2, 8)
graph.Print()
Kruskals(graph)

}

0 comments on commit f00d068

Please sign in to comment.