Sorting
Quick Sort (Lomuto)
Choose the last item as a pivot, partition smaller values to its left, then recurse on the two sides.
Algorithm
Basic Implementation
basic.sh
#!/usr/bin/env bash
set -euo pipefail
partition() {
local low=$1
local high=$2
local pivot=${arr[high]}
local i=$((low - 1))
local j
local tmp
for ((j = low; j < high; j++)); do
if ((arr[j] <= pivot)); then
i=$((i + 1))
tmp=${arr[i]}
arr[i]=${arr[j]}
arr[j]=$tmp
fi
done
tmp=${arr[i+1]}
arr[i+1]=${arr[high]}
arr[high]=$tmp
pivot_index=$((i + 1))
}
quick_sort() {
local low=$1
local high=$2
if ((low < high)); then
partition "$low" "$high"
local p=$pivot_index
quick_sort "$low" "$((p - 1))"
quick_sort "$((p + 1))" "$high"
fi
}
arr=(4 1 5 2 3)
pivot_index=0
quick_sort 0 $((${#arr[@]} - 1))
printf '['
sep=''
for v in "${arr[@]}"; do
printf '%s%d' "$sep" "$v"
sep=', '
done
printf ']\n'
Complexity
- Time: O(n^2) worst, O(n log n) average
- Space: O(log n) average call stack
- Stable: no
Implementation notes
arr=(4 1 5 2 3)is the pinned Bash indexed array, andquick_sortmutates it in place by index.quick_sort "$low" "$high"receives integer bounds.if ((low < high))is Bash arithmetic evaluation for the recursive base case.partition "$low" "$high"chooses the last element as the pivot withpivot=${arr[high]}.i=$((low - 1))marks the end of the smaller-or-equal region. The scan variablejwalks fromlowtohigh - 1.if ((arr[j] <= pivot)); thenis a numeric comparison. When it passes,imoves right and thetmplines swaparr[i]witharr[j].- After the scan, another
tmpswap moves the pivot intoarr[i+1], andpivot_index=$((i + 1))tellsquick_sortwhere to split. - The recursive calls sort
low..p-1andp+1..high. Lomuto quicksort is not stable because swaps can move equal values around.
First partition replay
pivot 3 in [4, 1, 5, 2, 3]
4 > 3: keep right side
1 <= 3: swap into left side -> [1, 4, 5, 2, 3]
5 > 3: keep right side
2 <= 3: swap into left side -> [1, 2, 5, 4, 3]
pivot swap: [1, 2, 3, 4, 5]
- Final output uses the shared Bash formatter:
printf '[',for v in "${arr[@]}",printf '%s%d' "$sep" "$v", andprintf ']\n'.
pivot
The final element is moved to the boundary between smaller and larger values.
partition
One scan rearranges the current range before the recursive calls.