diff --git a/src/SortingAlgorithms.jl b/src/SortingAlgorithms.jl index 50f668b..da85152 100644 --- a/src/SortingAlgorithms.jl +++ b/src/SortingAlgorithms.jl @@ -8,15 +8,17 @@ import Base.Collections.heapify!, Base.Collections.percolate_down! -export HeapSort, TimSort, RadixSort +export HeapSort, IntroSort, RadixSort, TimSort immutable HeapSortAlg <: Algorithm end -immutable TimSortAlg <: Algorithm end +immutable IntroSortAlg <: Algorithm end immutable RadixSortAlg <: Algorithm end +immutable TimSortAlg <: Algorithm end const HeapSort = HeapSortAlg() -const TimSort = TimSortAlg() +const IntroSort = IntroSortAlg() const RadixSort = RadixSortAlg() +const TimSort = TimSortAlg() ## Heap sort @@ -560,4 +562,55 @@ function sort!(v::AbstractVector, lo::Int, hi::Int, ::TimSortAlg, o::Ordering) return v end + +## Intro sort + +function sort!(v::AbstractVector, lo::Int, hi::Int, a::IntroSortAlg, o::Ordering) + N = length(v) + if N > 1 + introsort_loop!(v, lo, hi, 2 * ifloor(log2(hi - lo + 1)), o) + sort!(v, lo, hi, InsertionSort, o) + end + v +end + +function introsort_loop!(v::AbstractVector, lo::Int, hi::Int, depth_limit::Int, o::Ordering) + while hi - lo > depth_limit + if depth_limit == 0 + sort!(v, lo, hi, HeapSort, o) + return v + end + depth_limit -= 1 + p = partition!(v, lo, hi, index_of_median_of_three(v, lo, hi, o), o) + introsort_loop!(v, p, hi, depth_limit, o) + hi = p + end + v +end + +function partition!(v::AbstractVector, lo::Int, hi::Int, p::Int, o::Ordering) + val = v[p] + v[p], v[hi] = v[hi], v[p] + j = lo + for i in lo:hi + if lt(o, v[i], val) + v[i], v[j] = v[j], v[i] + j += 1 + end + end + v[j], v[hi] = v[hi], v[j] + return j +end + +function index_of_median_of_three(v, lo, hi, o) + middle = lo + div(hi - lo, 2) + if lt(o, v[lo], v[middle]) + return lt(o, v[middle], v[hi]) ? middle : hi + elseif lt(o, v[hi], v[middle]) + return middle + else + return lt(o, v[lo], v[hi]) ? lo : hi + end +end + end # module diff --git a/test/runtests.jl b/test/runtests.jl index acb8ab6..8ee56b3 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -3,7 +3,7 @@ using SortingAlgorithms a = rand(1:10000, 1000) -for alg in {TimSort, HeapSort, RadixSort} +for alg in {HeapSort, IntroSort, RadixSort, TimSort} b = sort(a, alg=alg) @test issorted(b) ix = sortperm(a, alg=alg) @@ -83,7 +83,7 @@ for n in [0:10, 100, 101, 1000, 1001] end # unstable algorithms - for alg in [HeapSort] + for alg in [HeapSort, IntroSort] p = sortperm(v, alg=alg, order=ord) @test isperm(p) @test v[p] == si