Sorting
Bubble Sort
Repeatedly walk the array, swapping adjacent out-of-order pairs. After each pass the largest unsorted element bubbles to its final position; stop early when a clean pass finds nothing to swap.
Algorithm
Canonical input arr=(5 1 4 2 8) finishes in three outer passes and
yields [1, 2, 4, 5, 8].
adjacent swaps
A single pass compares each adjacent pair `arr[j], arr[j+1]` and swaps when out of order.
early termination
A `swapped` flag detects an already-sorted suffix; clearing it ends the outer loop before doing unnecessary passes.
Basic Implementation
basic.sh
Replay: real traced execution (multi-file project)
#!/usr/bin/env bash
set -euo pipefail
arr=(5 1 4 2 8)
n=${#arr[@]}
i=0
while [ "$i" -lt "$((n - 1))" ]; do
swapped=0
j=0
while [ "$j" -lt "$((n - i - 1))" ]; do
if [ "${arr[j]}" -gt "${arr[j+1]}" ]; then
tmp=${arr[j]}
arr[j]=${arr[j+1]}
arr[j+1]=$tmp
swapped=1
fi
j=$((j + 1))
done
if [ "$swapped" -eq 0 ]; then
break
fi
i=$((i + 1))
done
printf '['
sep=''
for v in "${arr[@]}"; do
printf '%s%d' "$sep" "$v"
sep=', '
done
printf ']\n'
arr ← [5, 1, 4, 2, 8]
2set -euo pipefail3arr=(5 1 4 2 8)4n=${#arr[@]}values this step[5, 1, 4, 2, 8]arrn ← 5
3arr=(5 1 4 2 8)4n=${#arr[@]}5i=0values this step5n[5, 1, 4, 2, 8]arrswapped ← 0
6while [ "$i" -lt "$((n - 1))" ]; do7 swapped=08 j=0values this step0swappedarr[j] > arr[j+1] ← true
9while [ "$j" -lt "$((n - i - 1))" ]; do10 if [ "${arr[j]}" -gt "${arr[j+1]}" ]; then11 tmp=${arr[j]}values this steptruearr[j] > arr[j+1][5, 1, 4, 2, 8]arr0j5arr[j]1arr[j+1]arr ← [1, 5, 4, 2, 8], swapped ← 1
11tmp=${arr[j]}12arr[j]=${arr[j+1]}13arr[j+1]=$tmpvalues this step[5, 1, 4, 2, 8] → [1, 5, 4, 2, 8]arr1swappedarr[j] > arr[j+1] ← true
9while [ "$j" -lt "$((n - i - 1))" ]; do10 if [ "${arr[j]}" -gt "${arr[j+1]}" ]; then11 tmp=${arr[j]}values this steptruearr[j] > arr[j+1][1, 5, 4, 2, 8]arr1j5arr[j]4arr[j+1]arr ← [1, 4, 5, 2, 8], swapped ← 1
11tmp=${arr[j]}12arr[j]=${arr[j+1]}13arr[j+1]=$tmpvalues this step[1, 5, 4, 2, 8] → [1, 4, 5, 2, 8]arr1swappedarr[j] > arr[j+1] ← true
9while [ "$j" -lt "$((n - i - 1))" ]; do10 if [ "${arr[j]}" -gt "${arr[j+1]}" ]; then11 tmp=${arr[j]}values this steptruearr[j] > arr[j+1][1, 4, 5, 2, 8]arr2j5arr[j]2arr[j+1]arr ← [1, 4, 2, 5, 8], swapped ← 1
11tmp=${arr[j]}12arr[j]=${arr[j+1]}13arr[j+1]=$tmpvalues this step[1, 4, 5, 2, 8] → [1, 4, 2, 5, 8]arr1swappedarr[j] > arr[j+1] ← false
9while [ "$j" -lt "$((n - i - 1))" ]; do10 if [ "${arr[j]}" -gt "${arr[j+1]}" ]; then11 tmp=${arr[j]}values this stepfalsearr[j] > arr[j+1][1, 4, 2, 5, 8]arr3j5arr[j]8arr[j+1]swapped ← 0
6while [ "$i" -lt "$((n - 1))" ]; do7 swapped=08 j=0values this step0swappedarr[j] > arr[j+1] ← false
9while [ "$j" -lt "$((n - i - 1))" ]; do10 if [ "${arr[j]}" -gt "${arr[j+1]}" ]; then11 tmp=${arr[j]}values this stepfalsearr[j] > arr[j+1][1, 4, 2, 5, 8]arr0j1arr[j]4arr[j+1]arr[j] > arr[j+1] ← true
9while [ "$j" -lt "$((n - i - 1))" ]; do10 if [ "${arr[j]}" -gt "${arr[j+1]}" ]; then11 tmp=${arr[j]}values this steptruearr[j] > arr[j+1][1, 4, 2, 5, 8]arr1j4arr[j]2arr[j+1]arr ← [1, 2, 4, 5, 8], swapped ← 1
11tmp=${arr[j]}12arr[j]=${arr[j+1]}13arr[j+1]=$tmpvalues this step[1, 4, 2, 5, 8] → [1, 2, 4, 5, 8]arr1swappedarr[j] > arr[j+1] ← false
9while [ "$j" -lt "$((n - i - 1))" ]; do10 if [ "${arr[j]}" -gt "${arr[j+1]}" ]; then11 tmp=${arr[j]}values this stepfalsearr[j] > arr[j+1][1, 2, 4, 5, 8]arr2j4arr[j]5arr[j+1]swapped ← 0
6while [ "$i" -lt "$((n - 1))" ]; do7 swapped=08 j=0values this step0swappedarr[j] > arr[j+1] ← false
9while [ "$j" -lt "$((n - i - 1))" ]; do10 if [ "${arr[j]}" -gt "${arr[j+1]}" ]; then11 tmp=${arr[j]}values this stepfalsearr[j] > arr[j+1][1, 2, 4, 5, 8]arr0j1arr[j]2arr[j+1]arr[j] > arr[j+1] ← false
9while [ "$j" -lt "$((n - i - 1))" ]; do10 if [ "${arr[j]}" -gt "${arr[j+1]}" ]; then11 tmp=${arr[j]}values this stepfalsearr[j] > arr[j+1][1, 2, 4, 5, 8]arr1j2arr[j]4arr[j+1]done ← true
18if [ "$swapped" -eq 0 ]; then19 break20fivalues this steptruedone0swappedstdout ← [1, 2, 4, 5, 8]
28done29printf ']\n'values this step[1, 2, 4, 5, 8]stdout[1, 2, 4, 5, 8]arr
Complexity
- Time: O(n^2) worst case, O(n) best with the early-termination check
- Space: O(1)
Implementation notes
- Bash: explicit nested
whilewith a manual three-line swap (tmp=${arr[j]}; arr[j]=${arr[j+1]}; arr[j+1]=$tmp) keeps the move visible. The shell has nosortfor in-process arrays; piping tosort -nwould promote the integers to text, fork another process, and skip the educational sorting loop entirely. - The
swappedflag uses0/1integer semantics and is checked with[ "$swapped" -eq 0 ]so the early-termination branch is explicit. - The replay records each compare frame, each swap frame, and the
swapped == 0 -> breakframe at the end of pass 3 so the viewer sees the early-exit fire.