heap.mx raw

   1  // Copyright 2009 The Go Authors. All rights reserved.
   2  // Use of this source code is governed by a BSD-style
   3  // license that can be found in the LICENSE file.
   4  
   5  // Package heap provides heap operations for any type that implements
   6  // heap.Interface. A heap is a tree with the property that each node is the
   7  // minimum-valued node in its subtree.
   8  //
   9  // The minimum element in the tree is the root, at index 0.
  10  //
  11  // A heap is a common way to implement a priority queue. To build a priority
  12  // queue, implement the Heap interface with the (negative) priority as the
  13  // ordering for the Less method, so Push adds items while Pop removes the
  14  // highest-priority item from the queue. The Examples include such an
  15  // implementation; the file example_pq_test.go has the complete source.
  16  package heap
  17  
  18  import "sort"
  19  
  20  // The Interface type describes the requirements
  21  // for a type using the routines in this package.
  22  // Any type that implements it may be used as a
  23  // min-heap with the following invariants (established after
  24  // [Init] has been called or if the data is empty or sorted):
  25  //
  26  //	!h.Less(j, i) for 0 <= i < h.Len() and 2*i+1 <= j <= 2*i+2 and j < h.Len()
  27  //
  28  // Note that [Push] and [Pop] in this interface are for package heap's
  29  // implementation to call. To add and remove things from the heap,
  30  // use [heap.Push] and [heap.Pop].
  31  type Interface interface {
  32  	sort.Interface
  33  	Push(x any) // add x as element Len()
  34  	Pop() any   // remove and return element Len() - 1.
  35  }
  36  
  37  // Init establishes the heap invariants required by the other routines in this package.
  38  // Init is idempotent with respect to the heap invariants
  39  // and may be called whenever the heap invariants may have been invalidated.
  40  // The complexity is O(n) where n = h.Len().
  41  func Init(h Interface) {
  42  	// heapify
  43  	n := h.Len()
  44  	for i := n/2 - 1; i >= 0; i-- {
  45  		down(h, i, n)
  46  	}
  47  }
  48  
  49  // Push pushes the element x onto the heap.
  50  // The complexity is O(log n) where n = h.Len().
  51  func Push(h Interface, x any) {
  52  	h.Push(x)
  53  	up(h, h.Len()-1)
  54  }
  55  
  56  // Pop removes and returns the minimum element (according to Less) from the heap.
  57  // The complexity is O(log n) where n = h.Len().
  58  // Pop is equivalent to [Remove](h, 0).
  59  func Pop(h Interface) any {
  60  	n := h.Len() - 1
  61  	h.Swap(0, n)
  62  	down(h, 0, n)
  63  	return h.Pop()
  64  }
  65  
  66  // Remove removes and returns the element at index i from the heap.
  67  // The complexity is O(log n) where n = h.Len().
  68  func Remove(h Interface, i int) any {
  69  	n := h.Len() - 1
  70  	if n != i {
  71  		h.Swap(i, n)
  72  		if !down(h, i, n) {
  73  			up(h, i)
  74  		}
  75  	}
  76  	return h.Pop()
  77  }
  78  
  79  // Fix re-establishes the heap ordering after the element at index i has changed its value.
  80  // Changing the value of the element at index i and then calling Fix is equivalent to,
  81  // but less expensive than, calling [Remove](h, i) followed by a Push of the new value.
  82  // The complexity is O(log n) where n = h.Len().
  83  func Fix(h Interface, i int) {
  84  	if !down(h, i, h.Len()) {
  85  		up(h, i)
  86  	}
  87  }
  88  
  89  func up(h Interface, j int) {
  90  	for {
  91  		i := (j - 1) / 2 // parent
  92  		if i == j || !h.Less(j, i) {
  93  			break
  94  		}
  95  		h.Swap(i, j)
  96  		j = i
  97  	}
  98  }
  99  
 100  func down(h Interface, i0, n int) bool {
 101  	i := i0
 102  	for {
 103  		j1 := 2*i + 1
 104  		if j1 >= n || j1 < 0 { // j1 < 0 after int overflow
 105  			break
 106  		}
 107  		j := j1 // left child
 108  		if j2 := j1 + 1; j2 < n && h.Less(j2, j1) {
 109  			j = j2 // = 2*i + 2  // right child
 110  		}
 111  		if !h.Less(j, i) {
 112  			break
 113  		}
 114  		h.Swap(i, j)
 115  		i = j
 116  	}
 117  	return i > i0
 118  }
 119