|
|
|
@ -139,4 +139,74 @@ function algo.bsearchr(array, what, less)
|
|
|
|
|
return lo + ofs
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local function merge(array, lo, mid, hi, less, workspace)
|
|
|
|
|
local i, j, k
|
|
|
|
|
i = 1
|
|
|
|
|
|
|
|
|
|
-- Copy first half of array to auxiliary array
|
|
|
|
|
for j = lo,mid do
|
|
|
|
|
workspace[i] = array[j]
|
|
|
|
|
i = i + 1
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
i = 1
|
|
|
|
|
j = mid + 1
|
|
|
|
|
k = lo
|
|
|
|
|
while k < j and j <= hi do
|
|
|
|
|
local v = array[j]
|
|
|
|
|
local el = workspace[i]
|
|
|
|
|
|
|
|
|
|
if less(v, el) then
|
|
|
|
|
array[k] = v
|
|
|
|
|
j = j + 1
|
|
|
|
|
else
|
|
|
|
|
array[k] = el
|
|
|
|
|
i = i + 1
|
|
|
|
|
end
|
|
|
|
|
k = k + 1
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- Copy back any remaining elements of first half
|
|
|
|
|
for k = k,j-1 do
|
|
|
|
|
array[k] = workspace[i]
|
|
|
|
|
i = i + 1
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local function mergesort(array, lo, hi, less, workspace)
|
|
|
|
|
if hi - lo < 72 then
|
|
|
|
|
_insertionsort(array, lo, hi, less)
|
|
|
|
|
else
|
|
|
|
|
local mid = floor((lo + hi)/2)
|
|
|
|
|
|
|
|
|
|
mergesort(array, lo, mid, less, workspace)
|
|
|
|
|
mergesort(array, mid + 1, hi, less, workspace)
|
|
|
|
|
merge(array, lo, mid, hi, less, workspace)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
--- Array stable sort, uses Merge Sort - O(n*log(n)).
|
|
|
|
|
--
|
|
|
|
|
-- Algorithm is a slightly altered version of stable_sort(),
|
|
|
|
|
-- posted on Lua-L by Steve Fisher on 02 May 2013 22:10:50
|
|
|
|
|
-- https://lua-users.org/lists/lua-l/2013-05/msg00038.html
|
|
|
|
|
--
|
|
|
|
|
-- This implementation uses an auxiliary buffer of size O(n/2).
|
|
|
|
|
--
|
|
|
|
|
-- @tparam table array Array to be sorted.
|
|
|
|
|
-- @tparam[opt=operator <] function less comparison function, takes 2 arguments,
|
|
|
|
|
-- returns true if its first argument is
|
|
|
|
|
-- less than its second argument,
|
|
|
|
|
-- false otherwise.
|
|
|
|
|
-- @tparam[opt={}] table use an existing workspace buffer instead of allocating one.
|
|
|
|
|
function algo.stablesort(array, less, workspace)
|
|
|
|
|
local n = #array
|
|
|
|
|
|
|
|
|
|
less = less or lt
|
|
|
|
|
workspace = workspace or {}
|
|
|
|
|
workspace[floor((n+1)/2)] = array[1] -- preallocate some room
|
|
|
|
|
|
|
|
|
|
mergesort(array, 1, n, less, workspace)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
return algo
|
|
|
|
|