mirror of
https://github.com/janet-lang/janet
synced 2024-11-19 15:14:48 +00:00
Improve quicksort to avoid worst case performance.
The current implementation will have quadratic behaviour for already sorted arrays because it picks the last element as pivot. In an sorted array this splits the array repeatedly into the biggest value and all other values. The implementation in this commit uses the *median of three* as pivot. `janet -e "(sort (range 10000))"` to reproduce quadratic behaviour.
This commit is contained in:
parent
cae4f19629
commit
3e742ffc4c
@ -790,35 +790,38 @@
|
|||||||
###
|
###
|
||||||
###
|
###
|
||||||
|
|
||||||
(defn- sort-part
|
(defn- median-of-three [a b c]
|
||||||
[a lo hi by]
|
(if (not= (> a b) (> a c))
|
||||||
(def pivot (in a hi))
|
a
|
||||||
(var i lo)
|
(if (not= (> b a) (> b c)) b c)))
|
||||||
(forv j lo hi
|
|
||||||
(def aj (in a j))
|
|
||||||
(when (by aj pivot)
|
|
||||||
(def ai (in a i))
|
|
||||||
(set (a i) aj)
|
|
||||||
(set (a j) ai)
|
|
||||||
(++ i)))
|
|
||||||
(set (a hi) (in a i))
|
|
||||||
(set (a i) pivot)
|
|
||||||
i)
|
|
||||||
|
|
||||||
(defn- sort-help
|
(defn sort-help [a lo hi by]
|
||||||
[a lo hi by]
|
(when (< lo hi)
|
||||||
(when (> hi lo)
|
(def pivot
|
||||||
(def piv (sort-part a lo hi by))
|
(median-of-three (in a hi) (in a lo)
|
||||||
(sort-help a lo (- piv 1) by)
|
(in a (math/floor (/ (+ lo hi) 2)))))
|
||||||
(sort-help a (+ piv 1) hi by))
|
(var left lo)
|
||||||
|
(var right hi)
|
||||||
|
(while true
|
||||||
|
(while (by (in a left) pivot) (++ left))
|
||||||
|
(while (by pivot (in a right)) (-- right))
|
||||||
|
(when (<= left right)
|
||||||
|
(def tmp (in a left))
|
||||||
|
(set (a left) (in a right))
|
||||||
|
(set (a right) tmp)
|
||||||
|
(++ left)
|
||||||
|
(-- right))
|
||||||
|
(if (>= left right) (break)))
|
||||||
|
(sort-help a lo right by)
|
||||||
|
(sort-help a left hi by))
|
||||||
a)
|
a)
|
||||||
|
|
||||||
(defn sort
|
(defn sort
|
||||||
"Sort an array in-place. Uses quick-sort and is not a stable sort."
|
"Sort an array in-place. Uses quick-sort and is not a stable sort."
|
||||||
[a &opt by]
|
[a &opt by]
|
||||||
(sort-help a 0 (- (length a) 1) (or by <)))
|
(sort-help a 0 (- (length a) 1) (or by <)))
|
||||||
|
|
||||||
(undef sort-part)
|
(undef median-of-three)
|
||||||
(undef sort-help)
|
(undef sort-help)
|
||||||
|
|
||||||
(defn sort-by
|
(defn sort-by
|
||||||
|
Loading…
Reference in New Issue
Block a user