本站源代码
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

164 lines
4.9KB

  1. // Copyright (c) 2015, Emir Pasic. 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. // Package binaryheap implements a binary heap backed by array list.
  5. //
  6. // Comparator defines this heap as either min or max heap.
  7. //
  8. // Structure is not thread safe.
  9. //
  10. // References: http://en.wikipedia.org/wiki/Binary_heap
  11. package binaryheap
  12. import (
  13. "fmt"
  14. "github.com/emirpasic/gods/lists/arraylist"
  15. "github.com/emirpasic/gods/trees"
  16. "github.com/emirpasic/gods/utils"
  17. "strings"
  18. )
  19. func assertTreeImplementation() {
  20. var _ trees.Tree = (*Heap)(nil)
  21. }
  22. // Heap holds elements in an array-list
  23. type Heap struct {
  24. list *arraylist.List
  25. Comparator utils.Comparator
  26. }
  27. // NewWith instantiates a new empty heap tree with the custom comparator.
  28. func NewWith(comparator utils.Comparator) *Heap {
  29. return &Heap{list: arraylist.New(), Comparator: comparator}
  30. }
  31. // NewWithIntComparator instantiates a new empty heap with the IntComparator, i.e. elements are of type int.
  32. func NewWithIntComparator() *Heap {
  33. return &Heap{list: arraylist.New(), Comparator: utils.IntComparator}
  34. }
  35. // NewWithStringComparator instantiates a new empty heap with the StringComparator, i.e. elements are of type string.
  36. func NewWithStringComparator() *Heap {
  37. return &Heap{list: arraylist.New(), Comparator: utils.StringComparator}
  38. }
  39. // Push adds a value onto the heap and bubbles it up accordingly.
  40. func (heap *Heap) Push(values ...interface{}) {
  41. if len(values) == 1 {
  42. heap.list.Add(values[0])
  43. heap.bubbleUp()
  44. } else {
  45. // Reference: https://en.wikipedia.org/wiki/Binary_heap#Building_a_heap
  46. for _, value := range values {
  47. heap.list.Add(value)
  48. }
  49. size := heap.list.Size()/2 + 1
  50. for i := size; i >= 0; i-- {
  51. heap.bubbleDownIndex(i)
  52. }
  53. }
  54. }
  55. // Pop removes top element on heap and returns it, or nil if heap is empty.
  56. // Second return parameter is true, unless the heap was empty and there was nothing to pop.
  57. func (heap *Heap) Pop() (value interface{}, ok bool) {
  58. value, ok = heap.list.Get(0)
  59. if !ok {
  60. return
  61. }
  62. lastIndex := heap.list.Size() - 1
  63. heap.list.Swap(0, lastIndex)
  64. heap.list.Remove(lastIndex)
  65. heap.bubbleDown()
  66. return
  67. }
  68. // Peek returns top element on the heap without removing it, or nil if heap is empty.
  69. // Second return parameter is true, unless the heap was empty and there was nothing to peek.
  70. func (heap *Heap) Peek() (value interface{}, ok bool) {
  71. return heap.list.Get(0)
  72. }
  73. // Empty returns true if heap does not contain any elements.
  74. func (heap *Heap) Empty() bool {
  75. return heap.list.Empty()
  76. }
  77. // Size returns number of elements within the heap.
  78. func (heap *Heap) Size() int {
  79. return heap.list.Size()
  80. }
  81. // Clear removes all elements from the heap.
  82. func (heap *Heap) Clear() {
  83. heap.list.Clear()
  84. }
  85. // Values returns all elements in the heap.
  86. func (heap *Heap) Values() []interface{} {
  87. return heap.list.Values()
  88. }
  89. // String returns a string representation of container
  90. func (heap *Heap) String() string {
  91. str := "BinaryHeap\n"
  92. values := []string{}
  93. for _, value := range heap.list.Values() {
  94. values = append(values, fmt.Sprintf("%v", value))
  95. }
  96. str += strings.Join(values, ", ")
  97. return str
  98. }
  99. // Performs the "bubble down" operation. This is to place the element that is at the root
  100. // of the heap in its correct place so that the heap maintains the min/max-heap order property.
  101. func (heap *Heap) bubbleDown() {
  102. heap.bubbleDownIndex(0)
  103. }
  104. // Performs the "bubble down" operation. This is to place the element that is at the index
  105. // of the heap in its correct place so that the heap maintains the min/max-heap order property.
  106. func (heap *Heap) bubbleDownIndex(index int) {
  107. size := heap.list.Size()
  108. for leftIndex := index<<1 + 1; leftIndex < size; leftIndex = index<<1 + 1 {
  109. rightIndex := index<<1 + 2
  110. smallerIndex := leftIndex
  111. leftValue, _ := heap.list.Get(leftIndex)
  112. rightValue, _ := heap.list.Get(rightIndex)
  113. if rightIndex < size && heap.Comparator(leftValue, rightValue) > 0 {
  114. smallerIndex = rightIndex
  115. }
  116. indexValue, _ := heap.list.Get(index)
  117. smallerValue, _ := heap.list.Get(smallerIndex)
  118. if heap.Comparator(indexValue, smallerValue) > 0 {
  119. heap.list.Swap(index, smallerIndex)
  120. } else {
  121. break
  122. }
  123. index = smallerIndex
  124. }
  125. }
  126. // Performs the "bubble up" operation. This is to place a newly inserted
  127. // element (i.e. last element in the list) in its correct place so that
  128. // the heap maintains the min/max-heap order property.
  129. func (heap *Heap) bubbleUp() {
  130. index := heap.list.Size() - 1
  131. for parentIndex := (index - 1) >> 1; index > 0; parentIndex = (index - 1) >> 1 {
  132. indexValue, _ := heap.list.Get(index)
  133. parentValue, _ := heap.list.Get(parentIndex)
  134. if heap.Comparator(parentValue, indexValue) <= 0 {
  135. break
  136. }
  137. heap.list.Swap(index, parentIndex)
  138. index = parentIndex
  139. }
  140. }
  141. // Check that the index is within bounds of the list
  142. func (heap *Heap) withinRange(index int) bool {
  143. return index >= 0 && index < heap.list.Size()
  144. }
上海开阖软件有限公司 沪ICP备12045867号-1