Sorting
Merge Sort (Top-Down)
Split the array recursively, sort each half, then merge two sorted runs into one sorted result.
Algorithm
Basic Implementation
basic.lua
local function merge_sort(values)
if #values <= 1 then return values end
local mid = math.floor(#values / 2)
local left, right = {}, {}
for i = 1, mid do left[#left + 1] = values[i] end
for i = mid + 1, #values do right[#right + 1] = values[i] end
left = merge_sort(left)
right = merge_sort(right)
local merged = {}
local i, j = 1, 1
while i <= #left and j <= #right do
if left[i] <= right[j] then merged[#merged + 1] = left[i]; i = i + 1
else merged[#merged + 1] = right[j]; j = j + 1 end
end
while i <= #left do merged[#merged + 1] = left[i]; i = i + 1 end
while j <= #right do merged[#merged + 1] = right[j]; j = j + 1 end
return merged
end
local arr = merge_sort({5, 1, 4, 2, 8})
io.write("[")
for k = 1, #arr do
if k > 1 then io.write(", ") end
io.write(tostring(arr[k]))
end
io.write("]\n")
Complexity
- Time: O(n log n)
- Space: O(n)
- Stable: yes
Implementation notes
merge_sort(values)takes a Lua table and returns a sorted table rather than mutating the original literal in place.- The checked input is
{5, 1, 4, 2, 8}, assigned throughlocal arr = merge_sort(...). - The base case is
if #values <= 1 then return values end. local mid = math.floor(#values / 2)splits the dense table length using integer flooring.- Halves are built with 1-based loops:
1..midfillsleft, andmid + 1..#valuesfillsright. - Appends use
table[#table + 1] = value, as inleft[#left + 1] = values[i]andmerged[#merged + 1] = left[i]. - The merge cursors start at
local i, j = 1, 1and advance while both halves still have values. - The comparison
left[i] <= right[j]keeps equal left-side values before right-side values. - The trace splits
[5, 1, 4, 2, 8]into[5, 1]and[4, 2, 8], sorts them into[1, 5]and[2, 4, 8], then merges[1, 2, 4, 5, 8]. - The final
io.writeloop prints[1, 2, 4, 5, 8].
divide and conquer
Each recursive call solves a smaller sorted subproblem.
merge step
Two sorted halves are combined by repeatedly taking the smaller front item.