Skip to content

Commit d496615

Browse files
authored
Djikstras Algorithm in golang div-bargali#234
Djikstras Algorithm in golang
2 parents 6887c92 + 60195f5 commit d496615

File tree

2 files changed

+254
-0
lines changed

2 files changed

+254
-0
lines changed
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"math"
6+
7+
"github.com/Data-Structures-and-Algorithms/Go/Algorithms/Graph-Algorithms/djikstras/minheapmap"
8+
)
9+
10+
//Using a MinHeap with O(1) Lookup for an implementation of the Djikstras algo for minimum cost spanning path.
11+
type node struct {
12+
name string //ID of the node
13+
neighbours map[*node]int // indicates a directed edge from the node to the neighbour
14+
}
15+
16+
func main() {
17+
//Build a graph representation..
18+
n1 := &node{
19+
name: "guitar",
20+
}
21+
n2 := &node{
22+
name: "book",
23+
}
24+
n3 := &node{
25+
name: "LP",
26+
}
27+
n4 := &node{
28+
name: "poster",
29+
}
30+
n5 := &node{
31+
name: "drums",
32+
}
33+
n6 := &node{
34+
name: "piano",
35+
}
36+
n1.neighbours = make(map[*node]int)
37+
n1.neighbours[n6] = 20
38+
n2.neighbours = make(map[*node]int)
39+
n2.neighbours[n4] = 0
40+
n2.neighbours[n3] = 5
41+
n3.neighbours = make(map[*node]int)
42+
n3.neighbours[n1] = 15
43+
n3.neighbours[n5] = 20
44+
n4.neighbours = make(map[*node]int)
45+
n4.neighbours[n5] = 10
46+
n4.neighbours[n1] = 30
47+
n5.neighbours = make(map[*node]int)
48+
n5.neighbours[n6] = 10
49+
src := n2
50+
// src: ok , adjList: ok
51+
mheap := minHeapMap{
52+
minHeap: make([]entry, 0),
53+
mapping: make(map[*node]int),
54+
}
55+
minheapmap.Push(&mheap, entry{
56+
n: n1,
57+
cost: math.MaxInt32,
58+
})
59+
minheapmap.Push(&mheap, entry{
60+
n: n3,
61+
cost: math.MaxInt32,
62+
})
63+
minheapmap.Push(&mheap, entry{
64+
n: n4,
65+
cost: math.MaxInt32,
66+
})
67+
minheapmap.Push(&mheap, entry{
68+
n: n5,
69+
cost: math.MaxInt32,
70+
})
71+
minheapmap.Push(&mheap, entry{
72+
n: n6,
73+
cost: math.MaxInt32,
74+
})
75+
minheapmap.Push(&mheap, entry{
76+
n: n2,
77+
cost: 0,
78+
})
79+
fmt.Println("created heap:", mheap.minHeap)
80+
srcMap := make(map[*node]*node)
81+
srcMap[src] = src
82+
costMap := make(map[*node]int)
83+
for len(mheap.minHeap) > 0 {
84+
top := minheapmap.Pop(&mheap).(entry)
85+
n := top.n
86+
fmt.Println("taking out", n.name)
87+
delete(mheap.mapping, n)
88+
c := top.cost
89+
fmt.Println("to reach", n.name, "cost:", c)
90+
costMap[n] = c
91+
for ngbr, cost := range n.neighbours {
92+
fmt.Println("at neighbr", ngbr.name, "edge cost:", cost)
93+
if mheap.contains(ngbr) {
94+
//current cost
95+
k := mheap.GetKey(ngbr)
96+
currCost := mheap.minHeap[k].cost
97+
fmt.Println("curr cost of reaching", ngbr.name, "-", currCost)
98+
//if current cost < c+cost
99+
if c+cost < currCost {
100+
mheap.minHeap[k].cost = c + cost
101+
fmt.Println("upgating", ngbr.name, "to", c+cost)
102+
minheapmap.Decrease(&mheap, ngbr)
103+
srcMap[ngbr] = n
104+
}
105+
// update cost of the ngbr in the heap
106+
}
107+
}
108+
109+
}
110+
for n, c := range costMap {
111+
fmt.Println("node:", n.name, " cost:", c)
112+
}
113+
114+
}
115+
116+
//need to implement decrement() in log(n) and contains in O(1)
117+
type minHeapMap struct {
118+
minHeap []entry
119+
mapping map[(*node)]int
120+
}
121+
122+
type entry struct {
123+
n *node
124+
cost int
125+
}
126+
127+
func (m *minHeapMap) contains(n *node) bool {
128+
_, ok := m.mapping[n]
129+
return ok
130+
}
131+
132+
func (m *minHeapMap) Remove(x interface{}) {
133+
delete((*m).mapping, x.(entry).n)
134+
}
135+
136+
func (m *minHeapMap) Update(k, v interface{}) {
137+
(*m).mapping[k.(entry).n] = v.(int)
138+
}
139+
140+
func (m minHeapMap) GetElem(x interface{}) interface{} {
141+
return (m).minHeap[x.(int)]
142+
}
143+
144+
func (m *minHeapMap) GetKey(x interface{}) int {
145+
return (*m).mapping[x.(*node)]
146+
}
147+
148+
func (m *minHeapMap) Len() int {
149+
return len((*m).minHeap)
150+
}
151+
152+
func (m *minHeapMap) Less(i, j int) bool {
153+
return ((*m).minHeap)[i].cost < ((*m).minHeap)[j].cost
154+
}
155+
156+
func (m *minHeapMap) Swap(i, j int) {
157+
(*m).minHeap[i], (*m).minHeap[j] = (*m).minHeap[j], (*m).minHeap[i]
158+
}
159+
160+
func (m *minHeapMap) Push(x interface{}) {
161+
(*m).minHeap = append((*m).minHeap, x.(entry))
162+
(*m).mapping[x.(entry).n] = len((*m).minHeap) - 1
163+
}
164+
165+
func (m *minHeapMap) Pop() interface{} {
166+
v := (*m).minHeap
167+
l := len(v)
168+
top := v[l-1]
169+
v = v[:l-1]
170+
(*m).minHeap = v
171+
return top
172+
}
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
package minheapmap
2+
3+
import "container/heap"
4+
5+
// The Interface type describes the requirements
6+
// for a type using the routines in this package.
7+
// Any type that implements it may be used as a
8+
// min-heap with the keys stored in a map
9+
10+
type Interface interface {
11+
heap.Interface
12+
//Remove an element from the corresponding Map for the heap entries
13+
Remove(x interface{})
14+
//Update a particular value of an entry in the heap and re-evaluate the heap invariance
15+
Update(k, v interface{})
16+
//Get the elem present at a particular index in the heap array
17+
GetElem(x interface{}) interface{}
18+
//Get the correspinding value to a key in the Map for the heap entries
19+
GetKey(x interface{}) int
20+
}
21+
22+
//Decrease the value associated with the key in the <key,value> tuple
23+
func Decrease(h Interface, k interface{}) {
24+
p := h.GetKey(k)
25+
if !down(h, p, h.Len()) {
26+
up(h, p)
27+
}
28+
}
29+
30+
// Push pushes the element x onto the heap.
31+
// The complexity is O(log n) where n = h.Len().
32+
// Push() is for the interface to call and should be used to add keys to the heap
33+
func Push(h Interface, x interface{}) {
34+
h.Push(x)
35+
up(h, h.Len()-1)
36+
}
37+
38+
// Pop removes and returns the minimum element (according to Less) from the heap.
39+
func Pop(h Interface) interface{} {
40+
n := h.Len() - 1
41+
h.Remove(h.GetElem(0))
42+
h.Update(h.GetElem(n), 0)
43+
h.Swap(0, n)
44+
down(h, 0, n)
45+
return h.Pop()
46+
}
47+
48+
func up(h Interface, j int) {
49+
for {
50+
i := (j - 1) / 2 // parent
51+
if i == j || !h.Less(j, i) {
52+
break
53+
}
54+
h.Update(h.GetElem(i), j)
55+
h.Update(h.GetElem(j), i)
56+
h.Swap(i, j)
57+
j = i
58+
}
59+
return
60+
}
61+
62+
func down(h Interface, i0, n int) bool {
63+
i := i0
64+
for {
65+
j1 := 2*i + 1
66+
if j1 >= n || j1 < 0 { // j1 < 0 after int overflow
67+
break
68+
}
69+
j := j1 // left child
70+
if j2 := j1 + 1; j2 < n && h.Less(j2, j1) {
71+
j = j2 // = 2*i + 2 // right child
72+
}
73+
if !h.Less(j, i) {
74+
break
75+
}
76+
h.Update(h.GetElem(i), j)
77+
h.Update(h.GetElem(j), i)
78+
h.Swap(i, j)
79+
i = j
80+
}
81+
return i > i0
82+
}

0 commit comments

Comments
 (0)