Skip to content

Commit 4b4521f

Browse files
petvanaLilithHafner
authored andcommitted
Doc: The default sorting alg. is stable from 1.9 (#47579)
* Update doc/src/base/sort.md * Update docs: The default sorting alg. is stable * Compat 1.9 for QuickSort to be stable * Specify the default algorithm * Use example from InlineStrings.jl * Change example to jldoctest * Remove "*appear* to be stable." as slightly misleading. Co-authored-by: Lilith Orion Hafner <[email protected]> (cherry picked from commit c5fe17b)
1 parent b19b2c1 commit 4b4521f

File tree

1 file changed

+47
-33
lines changed

1 file changed

+47
-33
lines changed

doc/src/base/sort.md

Lines changed: 47 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -141,53 +141,67 @@ There are currently four sorting algorithms available in base Julia:
141141
* [`PartialQuickSort(k)`](@ref)
142142
* [`MergeSort`](@ref)
143143

144-
`InsertionSort` is an O(n^2) stable sorting algorithm. It is efficient for very small `n`, and
145-
is used internally by `QuickSort`.
144+
`InsertionSort` is an O(n²) stable sorting algorithm. It is efficient for very small `n`,
145+
and is used internally by `QuickSort`.
146146

147-
`QuickSort` is an O(n log n) sorting algorithm which is in-place, very fast, but not stable –
148-
i.e. elements which are considered equal will not remain in the same order in which they originally
149-
appeared in the array to be sorted. `QuickSort` is the default algorithm for numeric values, including
150-
integers and floats.
147+
`QuickSort` is a very fast sorting algorithm with an average-case time complexity of
148+
O(n log n). `QuickSort` is stable, i.e., elements considered equal will remain in the same
149+
order. Notice that O(n²) is worst-case complexity, but it gets vanishingly unlikely as the
150+
pivot selection is randomized.
151151

152-
`PartialQuickSort(k)` is similar to `QuickSort`, but the output array is only sorted up to index
153-
`k` if `k` is an integer, or in the range of `k` if `k` is an `OrdinalRange`. For example:
152+
`PartialQuickSort(k::OrdinalRange)` is similar to `QuickSort`, but the output array is only
153+
sorted in the range of `k`. For example:
154154

155-
```julia
156-
x = rand(1:500, 100)
157-
k = 50
158-
k2 = 50:100
159-
s = sort(x; alg=QuickSort)
160-
ps = sort(x; alg=PartialQuickSort(k))
161-
qs = sort(x; alg=PartialQuickSort(k2))
162-
map(issorted, (s, ps, qs)) # => (true, false, false)
163-
map(x->issorted(x[1:k]), (s, ps, qs)) # => (true, true, false)
164-
map(x->issorted(x[k2]), (s, ps, qs)) # => (true, false, true)
165-
s[1:k] == ps[1:k] # => true
166-
s[k2] == qs[k2] # => true
155+
```jldoctest
156+
julia> x = rand(1:500, 100);
157+
158+
julia> k = 50:100;
159+
160+
julia> s1 = sort(x; alg=QuickSort);
161+
162+
julia> s2 = sort(x; alg=PartialQuickSort(k));
163+
164+
julia> map(issorted, (s1, s2))
165+
(true, false)
166+
167+
julia> map(x->issorted(x[k]), (s1, s2))
168+
(true, true)
169+
170+
julia> s1[k] == s2[k]
171+
true
167172
```
168173

174+
!!! compat "Julia 1.9"
175+
The `QuickSort` and `PartialQuickSort` algorithms are stable since Julia 1.9.
176+
169177
`MergeSort` is an O(n log n) stable sorting algorithm but is not in-place – it requires a temporary
170178
array of half the size of the input array – and is typically not quite as fast as `QuickSort`.
171179
It is the default algorithm for non-numeric data.
172180

173-
The default sorting algorithms are chosen on the basis that they are fast and stable, or *appear*
174-
to be so. For numeric types indeed, `QuickSort` is selected as it is faster and indistinguishable
175-
in this case from a stable sort (unless the array records its mutations in some way). The stability
176-
property comes at a non-negligible cost, so if you don't need it, you may want to explicitly specify
177-
your preferred algorithm, e.g. `sort!(v, alg=QuickSort)`.
181+
The default sorting algorithms are chosen on the basis that they are fast and stable.
182+
Usually, `QuickSort` is selected, but `InsertionSort` is preferred for small data.
183+
You can also explicitly specify your preferred algorithm, e.g.
184+
`sort!(v, alg=PartialQuickSort(10:20))`.
178185

179-
The mechanism by which Julia picks default sorting algorithms is implemented via the `Base.Sort.defalg`
180-
function. It allows a particular algorithm to be registered as the default in all sorting functions
181-
for specific arrays. For example, here are the two default methods from [`sort.jl`](https://github.com/JuliaLang/julia/blob/master/base/sort.jl):
186+
The mechanism by which Julia picks default sorting algorithms is implemented via the
187+
`Base.Sort.defalg` function. It allows a particular algorithm to be registered as the
188+
default in all sorting functions for specific arrays. For example, here is the default
189+
method from [`sort.jl`](https://github.com/JuliaLang/julia/blob/master/base/sort.jl):
190+
191+
```julia
192+
defalg(v::AbstractArray) = DEFAULT_STABLE
193+
```
182194

195+
You may change the default behavior for specific types by defining new methods for `defalg`.
196+
For example, [InlineStrings.jl](https://github.com/JuliaStrings/InlineStrings.jl/blob/v1.3.2/src/InlineStrings.jl#L903)
197+
defines the following method:
183198
```julia
184-
defalg(v::AbstractArray) = MergeSort
185-
defalg(v::AbstractArray{<:Number}) = QuickSort
199+
Base.Sort.defalg(::AbstractArray{<:Union{SmallInlineStrings, Missing}}) = InlineStringSort
186200
```
187201

188-
As for numeric arrays, choosing a non-stable default algorithm for array types for which the notion
189-
of a stable sort is meaningless (i.e. when two values comparing equal can not be distinguished)
190-
may make sense.
202+
!!! compat "Julia 1.9"
203+
The default sorting algorithm (returned by `Base.Sort.defalg`) is guaranteed
204+
to be stable since Julia 1.9. Previous versions had unstable edge cases when sorting numeric arrays.
191205

192206
## Alternate orderings
193207

0 commit comments

Comments
 (0)