func siftDownMin(h heap.Interface, i, n int) { for (i*2+2)*2+2 < n { // has four grandchildren m := minGrandchild(h, i, n) if h.Less(i, m) { return } h.Swap(i, m) if h.Less(parent(m), m) { h.Swap(m, parent(m)) } i = m } if hasChild(i, n) { m := minTwoGen(h, i, n) if m > i*2+2 { // must be a grandchild if h.Less(m, i) { h.Swap(i, m) if h.Less(parent(m), m) { h.Swap(m, parent(m)) } siftDownMin(h, m, n) } } else if h.Less(m, i) { h.Swap(i, m) } } }
// Iterative version after Bojesen, "Heap implementations and variations", // http://www.diku.dk/forskning/performance-engineering/Jesper/heaplab/heapsurvey_html/node11.html func siftDownMax(h heap.Interface, i, n int) { for (i*2+2)*2+2 < n { // has four grandchildren m := maxGrandchild(h, i, n) if h.Less(m, i) { return } h.Swap(i, m) if h.Less(m, parent(m)) { h.Swap(m, parent(m)) } i = m } // XXX Following is from the original paper; couldn't get Bojesen's version // to work. if hasChild(i, n) { m := maxTwoGen(h, i, n) if m > i*2+2 { // must be a grandchild if h.Less(i, m) { h.Swap(i, m) if h.Less(m, parent(m)) { h.Swap(m, parent(m)) } siftDownMax(h, m, n) } } else if h.Less(i, m) { h.Swap(i, m) } } }
func siftUpMin(h heap.Interface, i int) { for gp := parent(parent(i)); gp >= 0; i, gp = gp, parent(parent(gp)) { if h.Less(gp, i) { break } h.Swap(i, gp) } }
func minGrandchild(h heap.Interface, i, n int) int { cg := (i*2+1)*2 + 1 m := cg for i := 1; i <= 3; i++ { if h.Less(cg+i, m) { m = cg + i } } return m }
// Index of minimum of children and grandchildren (if any) of i. // Precondition: i has at least one child. func minTwoGen(h heap.Interface, i, n int) int { c1, c2 := i*2+1, i*2+2 m := c1 for _, k := range []int{c2, c1*2 + 1, c1*2 + 2, c2*2 + 1, c2*2 + 2} { if k >= n { break } if h.Less(k, m) { m = k } } return m }
// Index of maximum element in h. // // There's no MinInd because the minimum of a heap is always at index zero. func MaxInd(h heap.Interface) (maxind int) { switch h.Len() { case 1: maxind = 0 case 2: maxind = 1 default: maxind = 1 if h.Less(1, 2) { maxind = 2 } } return }
// Removes and returns the maximum element of h. func PopMax(h heap.Interface) interface{} { n := h.Len() if n <= 2 { return h.Pop() } i := 1 if h.Less(1, 2) { i = 2 } h.Swap(i, n-1) x := h.Pop() siftDownMax(h, i, n-1) return x }
func siftUp(h heap.Interface, i int) { if minLevel(i) { if i > 0 && h.Less(parent(i), i) { h.Swap(i, parent(i)) siftUpMax(h, parent(i)) } else { siftUpMin(h, i) } } else { if i > 0 && h.Less(i, parent(i)) { h.Swap(i, parent(i)) siftUpMin(h, parent(i)) } else { siftUpMax(h, i) } } }