|
10 | 10 |
|
11 | 11 | /** |
12 | 12 | * ============================================================================ |
13 | | - * = Sorting Algorithms = |
| 13 | + * = Sorting Algorithms Visualization = |
14 | 14 | * ============================================================================ |
15 | | - * Insertion sort is efficient for small arrays. Think of it like playing |
16 | | - * cards: you're holding sorted cards in your left hand (sorted prefix/subarray) |
17 | | - * and holding a card in your right hand (key). You insert the current card into |
18 | | - * the sorted cards until there is no card in the table (unsorted subarray). |
| 15 | + * |
| 16 | + * This example demonstrates four sorting algorithms: Bubble Sort, Insertion |
| 17 | + * Sort, Selection Sort, and Quick Sort. Each algorithm is visualized with a |
| 18 | + * bar chart of the array elements. |
| 19 | + * |
19 | 20 | */ |
20 | 21 |
|
21 | 22 | recho.button("Run", run); |
22 | 23 |
|
| 24 | +//➜ Bubble Sort |
| 25 | +//➜ ▁ |
| 26 | +//➜ ▁▂▄▄▄▅▆▆▆██████ |
| 27 | +//➜ ▁▁ ▂ ▇ ▇█ █ ▄ ███████████████ |
| 28 | +//➜ ▂▅▆██ █ █▇████▆█ ███████████████ |
| 29 | +//➜ ▂▅▇██████ █ ████████ ▅ ███████████████ |
| 30 | +//➜ ▁▇█████████▂█▁████████▁█▂███████████████ |
| 31 | +visualize(array.slice(), sortBubble, "Bubble Sort"); |
| 32 | + |
23 | 33 | //➜ Insertion Sort |
24 | | -//➜ ▁ |
25 | | -//➜ ▃▃▇█▃ ▃ █ |
26 | | -//➜ ▂▃▃▆▆██████▆ █ ██ ▇ ▁ ▄ |
27 | | -//➜ ▄▅████████████ █ ▅██▇█ █ ▂ █ |
28 | | -//➜ ▁▂▂▃▇████████████████ █▃███████▆█▃█ |
29 | | -//➜ ▁▄▅▆██████████████████████▄█████████████ |
30 | | -visualize(array, insertionSort, "Insertion Sort"); |
31 | | - |
32 | | -function* insertionSort(array) { |
33 | | - for (let i = 1; i < array.length; i++) { |
34 | | - const key = array[i]; |
35 | | - let j = i - 1; |
36 | | - while (j >= 0 && array[j] > key) { |
37 | | - array[j + 1] = array[j]; |
38 | | - yield array.slice(); |
39 | | - j--; |
40 | | - } |
41 | | - array[j + 1] = key; |
42 | | - yield array.slice(); |
43 | | - } |
44 | | - yield array.slice(); |
45 | | - return array; |
46 | | -} |
| 34 | +//➜ ▁ |
| 35 | +//➜ ▄▆▆██ ▆ ▁ ▂█▄ █ ▄█ █ ▅ |
| 36 | +//➜ ▁▂████████ █ ███▇▁ █ ▇ ██ █ ▄ █ |
| 37 | +//➜ ▅▆██████████ █▂█████ █ █▇████▆█ █ |
| 38 | +//➜ ▂▇█████████████▅███████ █ ████████ ▅ █ |
| 39 | +//➜ ▁▇███████████████████████▂█▁████████▁█▂█ |
| 40 | +visualize(array.slice(), sortInsertion, "Insertion Sort"); |
| 41 | + |
| 42 | +//➜ Selection Sort |
| 43 | +//➜ ▁ |
| 44 | +//➜ ▆█▁▄▂█▄ ▆█ ▄█ █ █▆ ▅ |
| 45 | +//➜ ▁████████▇▁███▇ ██ █ ▄██▂█ |
| 46 | +//➜ ▂▅▆███████████████▇████▆█████ |
| 47 | +//➜ ▂▅▅▇██████████████████████████████ |
| 48 | +//➜ ▁▁▁▂▂▇██████████████████████████████████ |
| 49 | +visualize(array.slice(), sortSelection, "Selection Sort"); |
| 50 | + |
| 51 | +//➜ Quick Sort |
| 52 | +//➜ ▁ |
| 53 | +//➜ ▁▄▂▄▄▅███▆███▆▆ |
| 54 | +//➜ ▁▂▁▄▇▇█████████████████ |
| 55 | +//➜ ▂▅▆▆▇████████████████████████ |
| 56 | +//➜ ▂▅▅▇██████████████████████████████ |
| 57 | +//➜ ▁▁▁▂▂▇██████████████████████████████████ |
| 58 | +visualize(array.slice(), sortQuick, "Quick Sort"); |
47 | 59 |
|
48 | 60 | const [array, setArray] = recho.state(data()); |
49 | 61 |
|
@@ -83,8 +95,76 @@ function visualize(array, sorter, label) { |
83 | 95 | } |
84 | 96 | echo.set("compact", true)(output); |
85 | 97 | } |
86 | | - }, 20); |
| 98 | + }, 100); |
87 | 99 | echo.dispose(() => clearInterval(timer)); |
88 | 100 | } |
89 | 101 |
|
| 102 | +function* sortSelection(array) { |
| 103 | + const n = array.length; |
| 104 | + yield array.slice(); |
| 105 | + for (let i = 0; i < n; i++) { |
| 106 | + let minIndex = i; |
| 107 | + for (let j = i + 1; j < n; j++) { |
| 108 | + if (array[j] < array[minIndex]) { |
| 109 | + minIndex = j; |
| 110 | + } |
| 111 | + } |
| 112 | + [array[i], array[minIndex]] = [array[minIndex], array[i]]; |
| 113 | + yield array.slice(); |
| 114 | + } |
| 115 | + yield array.slice(); |
| 116 | + return array; |
| 117 | +} |
| 118 | + |
| 119 | +function* sortInsertion(array) { |
| 120 | + const n = array.length; |
| 121 | + yield array.slice(); |
| 122 | + for (let i = 1; i < n; i++) { |
| 123 | + const current = array[i]; |
| 124 | + let j = i - 1; |
| 125 | + while (j >= 0 && array[j] > current) { |
| 126 | + array[j + 1] = array[j]; |
| 127 | + j--; |
| 128 | + } |
| 129 | + array[j + 1] = current; |
| 130 | + yield array.slice(); |
| 131 | + } |
| 132 | + yield array.slice(); |
| 133 | + return array; |
| 134 | +} |
| 135 | + |
| 136 | +function* sortBubble(array) { |
| 137 | + const n = array.length; |
| 138 | + yield array.slice(); |
| 139 | + for (let i = 0; i < n; i++) { |
| 140 | + for (let j = 0; j < n - i - 1; j++) { |
| 141 | + if (array[j] > array[j + 1]) { |
| 142 | + [array[j], array[j + 1]] = [array[j + 1], array[j]]; |
| 143 | + } |
| 144 | + } |
| 145 | + yield array.slice(); |
| 146 | + } |
| 147 | + yield array.slice(); |
| 148 | + return array; |
| 149 | +} |
| 150 | + |
| 151 | +function* sortQuick(array, left = 0, right = array.length - 1) { |
| 152 | + if (left >= right) return; |
| 153 | + |
| 154 | + let pivot = array[right]; // Pick the rightmost element as pivot. |
| 155 | + let i = left; |
| 156 | + for (let j = left; j < right; j++) { |
| 157 | + if (array[j] < pivot) { |
| 158 | + [array[i], array[j]] = [array[j], array[i]]; |
| 159 | + i++; |
| 160 | + } |
| 161 | + } |
| 162 | + [array[i], array[right]] = [array[right], array[i]]; |
| 163 | + yield array.slice(); |
| 164 | + |
| 165 | + yield* sortQuick(array, left, i - 1); |
| 166 | + yield* sortQuick(array, i + 1, right); |
| 167 | +} |
| 168 | + |
90 | 169 | const d3 = recho.require("d3"); |
| 170 | + |
0 commit comments