github.com/LdDl/ch@v1.7.8/heap_typed.go (about) 1 package ch 2 3 /* Copied from container/heap - https://golang.org/pkg/container/heap/ */ 4 // Why make copy? Just want to avoid type conversion 5 6 type distanceHeap []*Vertex 7 8 func (h distanceHeap) Len() int { return len(h) } 9 func (h distanceHeap) Less(i, j int) bool { return h[i].distance.distance < h[j].distance.distance } 10 func (h distanceHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] } 11 12 /* Actual code of interface implementation */ 13 // type Interface interface { 14 // Len() int <-- taken from sort.Interface 15 // Less(i, j int) bool <-- taken from sort.Interface 16 // Swap(i, j int) <-- taken from sort.Interface 17 // Push(x *Vertex) // add x as element Len() 18 // Pop() *Vertex // remove and return element Len() - 1. 19 // } 20 21 // Push pushes the element x onto the heap. 22 // The complexity is O(log n) where n = h.Len(). 23 func (h *distanceHeap) Push(x *Vertex) { 24 *h = append(*h, x) 25 h.up(h.Len() - 1) 26 } 27 28 // Pop removes and returns the minimum element (according to Less) from the heap. 29 // The complexity is O(log n) where n = h.Len(). 30 // Pop is equivalent to Remove(h, 0). 31 func (h *distanceHeap) Pop() *Vertex { 32 n := h.Len() - 1 33 h.Swap(0, n) 34 h.down(0, n) 35 heapSize := len(*h) 36 lastNode := (*h)[heapSize-1] 37 *h = (*h)[0 : heapSize-1] 38 return lastNode 39 } 40 41 // Remove removes and returns the element at index i from the heap. 42 // The complexity is O(log n) where n = h.Len(). 43 func (h distanceHeap) Remove(i int) *Vertex { 44 n := h.Len() - 1 45 if n != i { 46 h.Swap(i, n) 47 if !h.down(i, n) { 48 h.up(i) 49 } 50 } 51 return h.Pop() 52 } 53 54 func (h distanceHeap) up(j int) { 55 for { 56 i := (j - 1) / 2 // parent 57 if i == j || !h.Less(j, i) { 58 break 59 } 60 h.Swap(i, j) 61 j = i 62 } 63 } 64 65 func (h distanceHeap) down(i0, n int) bool { 66 i := i0 67 for { 68 j1 := 2*i + 1 69 if j1 >= n || j1 < 0 { // j1 < 0 after int overflow 70 break 71 } 72 j := j1 // left child 73 if j2 := j1 + 1; j2 < n && h.Less(j2, j1) { 74 j = j2 // = 2*i + 2 // right child 75 } 76 if !h.Less(j, i) { 77 break 78 } 79 h.Swap(i, j) 80 i = j 81 } 82 return i > i0 83 }