priority_queue.bmx 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. Strict
  2. 'Module PUB.PriorityQueue
  3. 'ModuleInfo "Author: Aaron Koolen"
  4. 'ModuleInfo "Version: 1.0"
  5. Rem
  6. This is an implementation of a priority queue implemented as
  7. a heap stored in an array.
  8. Note, it might not be the most optimised code, as I don't know some
  9. of the BlitzMax tricks that I might be able to do here.
  10. Let me know if you see anything simple too slow or crappy.
  11. End Rem
  12. ' You should derive your nodes from this class
  13. '
  14. Type PriorityQueueNode
  15. Method setKey(key:Float)
  16. _key = key;
  17. End Method
  18. Field _key:Float ' I don't think blitz max has the concept of templated types?
  19. End Type
  20. ' Main PriorityQueue class
  21. Type PriorityQueue
  22. ' private
  23. Field _contents:PriorityQueueNode[]
  24. Field _size:Int = 0
  25. Field _sizeSet:Int = 0
  26. ' public
  27. ' Must call this first before you do anything
  28. Method setMaxSize(newSize:Int)
  29. Assert newSize > 0, "Must set size of queue > 0"
  30. _contents = New PriorityQueueNode[newSize + 1] ' We don't add any, you have to add them
  31. _size = 0
  32. _sizeSet = newSize
  33. End Method
  34. '---------------------------------------
  35. ' Queue manipulation
  36. '---------------------------------------
  37. ' Insert a node into the queue
  38. Method insert(newNode:PriorityQueueNode)
  39. Assert _sizeSet > 0,"Must call setMaxSize first with size > 0"
  40. Assert _size < _sizeSet, "Queue is full"
  41. _size = _size + 1
  42. _contents[_size] = newNode
  43. _reheapUp(_size)
  44. End Method
  45. ' Remove and return a node from the queue and re-sort queue
  46. Method remove:PriorityQueueNode(index:Int = 1)
  47. Local node:PriorityQueueNode = _contents[index]
  48. _contents[index] = _contents[_size]
  49. _size = _size - 1
  50. _reheapDown(index, _size)
  51. Return node
  52. End Method
  53. '---------------------------------------
  54. ' Queue searching
  55. '---------------------------------------
  56. Method find:Int(node:PriorityQueueNode)
  57. Local t
  58. For t = 1 To _size
  59. If node = _contents[t]
  60. Return t
  61. EndIf
  62. Next
  63. Return 0
  64. End Method
  65. ' Return the current size of the queue
  66. Method size:Int()
  67. Return _size
  68. End Method
  69. ' Helper function for returning the nodes as an ordered list
  70. Method returnList:TList()
  71. Local list:Tlist = New TList
  72. Local a:PriorityQueueNode
  73. For a = EachIn _contents
  74. list.AddLast(remove(1)) ' The '1' here removes the top item
  75. Next
  76. Return list
  77. End Method
  78. '------------------------------------------------
  79. ' PRIVATE
  80. '------------------------------------------------
  81. ' Reheap an inserted item
  82. ' ARGUMENTS:
  83. ' index - The Index of the newly inserted item
  84. Method _reheapUp(index:Int)
  85. Local parentIndex = _parent(index)
  86. Local ok = False
  87. While( index > 1 And ok = False )
  88. If _contents[parentIndex]._key < _contents[index]._key Then
  89. ok = True
  90. Else
  91. Local temp:PriorityQueueNode = _contents[parentIndex]
  92. _contents[parentIndex] = _contents[index]
  93. _contents[index] = temp
  94. index = parentIndex
  95. parentIndex = _parent(index)
  96. EndIf
  97. Wend
  98. Return index
  99. End Method
  100. ' Reheaps downward - Called after a delete of a node
  101. ' ARGUMENTS:
  102. ' root - Index of the root (Top of tree) item
  103. ' bottom - The index of the last item in the tree
  104. Method _reheapDown(root:Int, bottom:Int)
  105. Local ok = False
  106. Local maxChild = 0
  107. While _left(root) <= bottom And ok = False
  108. If _left(root) = bottom
  109. maxChild = _left(root)
  110. Else
  111. If _contents[_left(root)]._key < _contents[_right(root)]._key
  112. maxChild = _left(root)
  113. Else
  114. maxChild = _right(root)
  115. EndIf
  116. EndIf
  117. If Not (_contents[root]._key < _contents[maxChild]._key) Then
  118. Local t:PriorityQueueNode = _contents[root]
  119. _contents[root] = _contents[maxChild]
  120. _contents[maxChild] = t
  121. root = maxChild
  122. Else
  123. ok = True
  124. EndIf
  125. Wend
  126. Return root
  127. End Method
  128. ' Returns the index of the parent node to a child node
  129. Method _parent:Int(childIndex:Int)
  130. Return childIndex / 2
  131. End Method
  132. ' Returns the index of the left child of a node
  133. Method _left:Int(siblingIndex:Int)
  134. Return siblingIndex * 2
  135. End Method
  136. ' Returns the index of the right child of a node
  137. Method _right:Int(siblingIndex:Int)
  138. Return siblingIndex * 2 +1
  139. End Method
  140. End Type