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  }