improve document for heapqueue (#16107)

This commit is contained in:
flywind 2020-11-24 21:29:34 +08:00 • committed by GitHub
commit afb8b69c0a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -6,20 +6,20 @@
# See the file "copying.txt", included in this # See the file "copying.txt", included in this
# distribution, for details about the copyright. # distribution, for details about the copyright.
##[
The `heapqueue` module implements a
`heap data structure<https://en.wikipedia.org/wiki/Heap_(data_structure)>`_
that can be used as a
`priority queue<https://en.wikipedia.org/wiki/Priority_queue>`_.
Heaps are arrays for which `a[k] <= a[2*k+1]` and `a[k] <= a[2*k+2]` for
all `k`, counting elements from 0. The interesting property of a heap is that
`a[0]` is always its smallest element.
Basic usage ## The `heapqueue` module implements a
----------- ## `heap data structure<https://en.wikipedia.org/wiki/Heap_(data_structure)>`_
.. code-block:: Nim ## that can be used as a
import heapqueue ## `priority queue<https://en.wikipedia.org/wiki/Priority_queue>`_.
## Heaps are arrays for which `a[k] <= a[2*k+1]` and `a[k] <= a[2*k+2]` for
## all `k`, counting elements from 0. The interesting property of a heap is that
## `a[0]` is always its smallest element.
##
## Basic usage
## -----------
##
runnableExamples:
var heap = initHeapQueue[int]() var heap = initHeapQueue[int]()
heap.push(8) heap.push(8)
heap.push(2) heap.push(2)
@ -31,14 +31,12 @@
# The lowest element remaining is 5 # The lowest element remaining is 5
assert heap[0] == 5 assert heap[0] == 5
Usage with custom object ## Usage with custom object
------------------------ ## ------------------------
To use a `HeapQueue` with a custom object, the `<` operator must be ## To use a `HeapQueue` with a custom object, the `<` operator must be
implemented. ## implemented.
.. code-block:: Nim
import heapqueue
runnableExamples:
type Job = object type Job = object
priority: int priority: int
@ -49,7 +47,7 @@
jobs.push(Job(priority: 2)) jobs.push(Job(priority: 2))
assert jobs[0].priority == 1 assert jobs[0].priority == 1
]##
import std/private/since import std/private/since
type HeapQueue*[T] = object type HeapQueue*[T] = object
@ -135,6 +133,9 @@ proc toHeapQueue*[T](x: openArray[T]): HeapQueue[T] {.since: (1, 3).} =
proc pop*[T](heap: var HeapQueue[T]): T = proc pop*[T](heap: var HeapQueue[T]): T =
## Pops and returns the smallest item from `heap`, ## Pops and returns the smallest item from `heap`,
## maintaining the heap invariant. ## maintaining the heap invariant.
runnableExamples:
var heap = toHeapQueue([9, 5, 8])
assert heap.pop() == 5
let lastelt = heap.data.pop() let lastelt = heap.data.pop()
if heap.len > 0: if heap.len > 0:
result = heap[0] result = heap[0]
@ -145,12 +146,22 @@ proc pop*[T](heap: var HeapQueue[T]): T =
proc find*[T](heap: HeapQueue[T], x: T): int {.since: (1, 3).} = proc find*[T](heap: HeapQueue[T], x: T): int {.since: (1, 3).} =
## Linear scan to find index of item ``x`` or -1 if not found. ## Linear scan to find index of item ``x`` or -1 if not found.
runnableExamples:
var heap = toHeapQueue([9, 5, 8])
assert heap.find(5) == 0
assert heap.find(9) == 1
assert heap.find(777) == -1
result = -1 result = -1
for i in 0 ..< heap.len: for i in 0 ..< heap.len:
if heap[i] == x: return i if heap[i] == x: return i
proc del*[T](heap: var HeapQueue[T], index: Natural) = proc del*[T](heap: var HeapQueue[T], index: Natural) =
## Removes the element at `index` from `heap`, maintaining the heap invariant. ## Removes the element at `index` from `heap`, maintaining the heap invariant.
runnableExamples:
var heap = toHeapQueue([9, 5, 8])
heap.del(1)
assert heap[0] == 5
assert heap[1] == 8
swap(heap.data[^1], heap.data[index]) swap(heap.data[^1], heap.data[index])
let newLen = heap.len - 1 let newLen = heap.len - 1
heap.data.setLen(newLen) heap.data.setLen(newLen)
@ -163,16 +174,28 @@ proc replace*[T](heap: var HeapQueue[T], item: T): T =
## more appropriate when using a fixed-size heap. Note that the value ## more appropriate when using a fixed-size heap. Note that the value
## returned may be larger than item! That constrains reasonable uses of ## returned may be larger than item! That constrains reasonable uses of
## this routine unless written as part of a conditional replacement: ## this routine unless written as part of a conditional replacement:
## runnableExamples:
## .. code-block:: nim var heap = initHeapQueue[int]()
## if item > heap[0]: heap.push(5)
## item = replace(heap, item) heap.push(12)
assert heap.replace(6) == 5
assert heap.len == 2
assert heap[0] == 6
assert heap.replace(4) == 6
result = heap[0] result = heap[0]
heap.data[0] = item heap.data[0] = item
siftup(heap, 0) siftup(heap, 0)
proc pushpop*[T](heap: var HeapQueue[T], item: T): T = proc pushpop*[T](heap: var HeapQueue[T], item: T): T =
## Fast version of a push followed by a pop. ## Fast version of a push followed by a pop.
runnableExamples:
var heap = initHeapQueue[int]()
heap.push(5)
heap.push(12)
assert heap.pushpop(6) == 5
assert heap.len == 2
assert heap[0] == 6
assert heap.pushpop(4) == 4
result = item result = item
if heap.len > 0 and heapCmp(heap.data[0], item): if heap.len > 0 and heapCmp(heap.data[0], item):
swap(result, heap.data[0]) swap(result, heap.data[0])