Skip to content

Commit 5d2defb

Browse files
committed
Update docs on custom ordering in heaps
1 parent 09719f5 commit 5d2defb

File tree

1 file changed

+60
-16
lines changed

1 file changed

+60
-16
lines changed

docs/src/heaps.md

Lines changed: 60 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -61,26 +61,40 @@ h = MutableBinaryMinHeap([1,4,3,2])
6161
h = MutableBinaryMaxHeap([1,4,3,2]) # create a mutable min/max heap from a vector
6262
```
6363

64-
Heaps may be constructed with a custom ordering. One use case for custom orderings
65-
is to achieve faster performance with `Float` elements with the risk of random ordering
66-
if any elements are `NaN`. The provided `DataStructures.FasterForward` and
67-
`DataStructures.FasterReverse` orderings are optimized for this purpose.
68-
Custom orderings may also be used for defining the order of structs as heap elements.
64+
## Using alternate orderings
65+
66+
Heaps can also use alternate orderings apart from the default one defined by
67+
`Base.isless`. This is accomplished by passing an instance of `Base.Ordering`
68+
as the first argument to the constructor. The top of the heap will then be the
69+
element that comes first according to this ordering.
70+
71+
The following example uses 2-tuples to track the index of each element in the
72+
original array, but sorts only by the data value:
73+
6974
```julia
70-
h = BinaryHeap{Float64, DataStructures.FasterForward}() # faster min heap
71-
h = BinaryHeap{Float64, DataStructures.FasterReverse}() # faster max heap
75+
data = collect(enumerate(["foo", "bar", "baz"]))
7276

73-
h = MutableBinaryHeap{Float64, DataStructures.FasterForward}() # faster mutable min heap
74-
h = MutableBinaryHeap{Float64, DataStructures.FasterReverse}() # faster mutable max heap
77+
h1 = BinaryHeap(data) # Standard lexicographic ordering for tuples
78+
first(h1) # => (1, "foo")
7579

76-
h = BinaryHeap{MyStruct, MyStructOrdering}() # heap containing custom struct
80+
h2 = BinaryHeap(Base.By(last), data) # Order by 2nd element only
81+
first(h2) # => (2, "bar")
82+
```
83+
84+
If the ordering type is a singleton it can be passed as a type parameter to the
85+
constructor instead:
86+
87+
```julia
88+
BinaryHeap{T, O}() # => BinaryHeap{T}(O())
89+
MutableBinaryHeap{T, O}() # => MutableBinaryHeap{T}(O())
7790
```
7891

7992
## Min-max heaps
8093
Min-max heaps maintain the minimum _and_ the maximum of a set,
8194
allowing both to be retrieved in constant (`O(1)`) time.
8295
The min-max heaps in this package are subtypes of `AbstractMinMaxHeap <: AbstractHeap`
8396
and have the same interface as other heaps with the following additions:
97+
8498
```julia
8599
# Let h be a min-max heap, k an integer
86100
minimum(h) # return the smallest element
@@ -95,6 +109,7 @@ popmax!(h, k) # remove and return the largest k elements
95109
popall!(h) # remove and return all the elements, sorted smallest to largest
96110
popall!(h, o) # remove and return all the elements according to ordering o
97111
```
112+
98113
The usual `first(h)` and `pop!(h)` are defined to be `minimum(h)` and `popmin!(h)`,
99114
respectively.
100115

@@ -115,13 +130,42 @@ Heaps can be used to extract the largest or smallest elements of an
115130
array without sorting the entire array first:
116131

117132
```julia
118-
nlargest(3, [0,21,-12,68,-25,14]) # => [68,21,14]
119-
nsmallest(3, [0,21,-12,68,-25,14]) # => [-25,-12,0]
133+
data = [0,21,-12,68,-25,14]
134+
nlargest(3, data) # => [68,21,14]
135+
nsmallest(3, data) # => [-25,-12,0]
136+
```
137+
138+
Both methods also support the `by` and `lt` keywords to customize the sort order,
139+
as in `Base.sort`:
140+
141+
```julia
142+
nlargest(3, data, by=x -> x^2) # => [68,-25,21]
143+
nsmallest(3, data, by=x -> x^2) # => [0,-12,14]
120144
```
121145

122-
Note that if the array contains floats and is free of NaN values,
123-
then the following alternatives may be used to achieve a 2x performance boost.
146+
The lower-level `DataStructures.nextreme` function takes a `Base.Ordering`
147+
instance as the first argument and returns the first `n` elements according to
148+
this ordering:
149+
150+
```julia
151+
DataStructures.nextreme(Base.Forward, n, a) # Equivalent to nsmallest(n, a)
124152
```
125-
DataStructures.nextreme(DataStructures.FasterReverse(), n, a) # faster nlargest(n, a)
126-
DataStructures.nextreme(DataStructures.FasterForward(), n, a) # faster nsmallest(n, a)
153+
154+
155+
# Improving performance with Float data
156+
157+
One use case for custom orderings is to achieve faster performance with `Float`
158+
elements with the risk of random ordering if any elements are `NaN`.
159+
The provided `DataStructures.FasterForward` and `DataStructures.FasterReverse`
160+
orderings are optimized for this purpose and may achive a 2x performance boost:
161+
162+
```julia
163+
h = BinaryHeap{Float64, DataStructures.FasterForward}() # faster min heap
164+
h = BinaryHeap{Float64, DataStructures.FasterReverse}() # faster max heap
165+
166+
h = MutableBinaryHeap{Float64, DataStructures.FasterForward}() # faster mutable min heap
167+
h = MutableBinaryHeap{Float64, DataStructures.FasterReverse}() # faster mutable max heap
168+
169+
DataStructures.nextreme(DataStructures.FasterReverse(), n, a) # faster nlargest(n, a)
170+
DataStructures.nextreme(DataStructures.FasterForward(), n, a) # faster nsmallest(n, a)
127171
```

0 commit comments

Comments
 (0)