Skip to content

Commit 438fc33

Browse files
Adding dijkstra algo
1 parent 79feb13 commit 438fc33

File tree

2 files changed

+189
-0
lines changed

2 files changed

+189
-0
lines changed

Go/greedy/dijkstra.go

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
package greedy
2+
3+
import (
4+
"fmt"
5+
"sort"
6+
)
7+
8+
const infinity = int(^uint(0) >> 1)
9+
10+
//Node : Holds the information for each vertex
11+
type Node struct {
12+
Name string
13+
}
14+
15+
// Edge holds information for each edge in the Graph
16+
type Edge struct {
17+
source *Node
18+
dest *Node
19+
cost int
20+
}
21+
22+
// Graph holds the graph
23+
type Graph struct {
24+
Edges []*Edge
25+
Nodes map[*Node]bool
26+
}
27+
28+
// AddNode : adds node in the graph
29+
func (g *Graph) AddNode(node *Node) {
30+
if g.Nodes == nil {
31+
g.Nodes = make(map[*Node]bool)
32+
}
33+
34+
if _, ok := g.Nodes[node]; !ok {
35+
g.Nodes[node] = true
36+
}
37+
}
38+
39+
// AddEdge : Adds edge in the graph
40+
func (g *Graph) AddEdge(src, dest *Node, cost int) {
41+
e := &Edge{
42+
source: src,
43+
dest: dest,
44+
cost: cost,
45+
}
46+
g.Edges = append(g.Edges, e)
47+
g.AddNode(src)
48+
g.AddNode(dest)
49+
}
50+
51+
// DijkstraGraphCreation : Starting point of Dijkstra Algo - Creates graph
52+
func DijkstraGraphCreation() map[*Node]int {
53+
a := &Node{"a"}
54+
b := &Node{"b"}
55+
c := &Node{"c"}
56+
d := &Node{"d"}
57+
e := &Node{"e"}
58+
f := &Node{"f"}
59+
g := &Node{"g"}
60+
61+
graph := Graph{}
62+
graph.AddEdge(c, a, 4)
63+
graph.AddEdge(c, f, 6)
64+
graph.AddEdge(a, f, 5)
65+
graph.AddEdge(a, d, 7)
66+
graph.AddEdge(f, d, 2)
67+
graph.AddEdge(a, b, 2)
68+
graph.AddEdge(d, b, 6)
69+
graph.AddEdge(d, g, 6)
70+
graph.AddEdge(f, g, 6)
71+
graph.AddEdge(b, g, 8)
72+
graph.AddEdge(b, e, 3)
73+
graph.AddEdge(g, e, 7)
74+
75+
costTable := graph.Dijkstra(a)
76+
for node, cost := range costTable {
77+
fmt.Printf("To reach destination[%v] from source[%v] = Cost[%d]", node, a, cost)
78+
}
79+
80+
return costTable
81+
82+
}
83+
84+
// Dijkstra : Dijkstra Algorithm Implementation
85+
func (g *Graph) Dijkstra(source *Node) map[*Node]int {
86+
costTable := createCostTable(g.Nodes, source)
87+
var visited []*Node
88+
89+
for len(visited) != len(g.Nodes) {
90+
node := g.getClosestNonVistedNode(costTable, visited)
91+
visited = append(visited, node)
92+
93+
for _, edges := range g.Edges {
94+
if edges.source == node {
95+
neighborCost := costTable[node] + edges.cost
96+
costTable[edges.dest] = min(neighborCost, costTable[edges.dest])
97+
} else if edges.dest == node {
98+
neighborCost := costTable[node] + edges.cost
99+
costTable[edges.source] = min(neighborCost, costTable[edges.source])
100+
}
101+
}
102+
fmt.Printf("\nNode[%v] costTable:", node.Name)
103+
showCostTable(costTable)
104+
}
105+
return costTable
106+
}
107+
108+
func showCostTable(costTable map[*Node]int) {
109+
for key, val := range costTable {
110+
fmt.Printf("\t Node[%v]-{%v} ", key.Name, val)
111+
}
112+
}
113+
114+
func min(a, b int) int {
115+
if a < b {
116+
return a
117+
}
118+
return b
119+
}
120+
121+
// getClosestNonVistedNode : creates a sorted cost table based on the non-vistied nodes and then returns the lowest cost node
122+
func (g *Graph) getClosestNonVistedNode(costTable map[*Node]int, visited []*Node) *Node {
123+
type costTableNode struct {
124+
node *Node
125+
cost int
126+
}
127+
128+
var costTableToSort []costTableNode
129+
130+
for node, cost := range costTable {
131+
isVisited := false
132+
for _, visitedNode := range visited {
133+
if node == visitedNode {
134+
isVisited = true
135+
}
136+
}
137+
138+
if !isVisited {
139+
costTableToSort = append(costTableToSort, costTableNode{node, cost})
140+
}
141+
}
142+
143+
sort.Slice(costTableToSort, func(i, j int) bool {
144+
return costTableToSort[i].cost < costTableToSort[j].cost
145+
})
146+
147+
return costTableToSort[0].node
148+
}
149+
150+
func createCostTable(nodes map[*Node]bool, source *Node) map[*Node]int {
151+
costTable := make(map[*Node]int)
152+
costTable[source] = 0
153+
154+
for key := range nodes {
155+
if key != source {
156+
costTable[key] = infinity
157+
}
158+
}
159+
return costTable
160+
}

Go/greedy/dijkstra_test.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package greedy
2+
3+
import (
4+
"testing"
5+
)
6+
7+
func TestDijkstraGraphCreation(t *testing.T) {
8+
tests := []struct {
9+
name string
10+
want map[*Node]int
11+
}{
12+
{
13+
name: "test-01",
14+
want: map[*Node]int{&Node{"a"}: 0, &Node{"b"}: 2, &Node{"c"}: 4, &Node{"d"}: 7, &Node{"e"}: 5, &Node{"f"}: 5, &Node{"g"}: 10},
15+
},
16+
}
17+
for _, tt := range tests {
18+
t.Run(tt.name, func(t *testing.T) {
19+
got := DijkstraGraphCreation()
20+
for key, val := range got {
21+
for testkey, testval := range tt.want {
22+
if key == testkey && val != testval {
23+
t.Errorf("DijkstraGraphCreation: Got={%v:%v} Want={%v:%v}", key, val, testkey, testval)
24+
}
25+
}
26+
}
27+
})
28+
}
29+
}

0 commit comments

Comments
 (0)