├── App ├── beep.js └── script.js ├── LICENSE ├── README.md ├── img └── Sorting Visualization.png ├── index.html └── style ├── Fonts ├── Pacifico-Regular.eot ├── Pacifico-Regular.ttf ├── Pacifico-Regular.woff └── Pacifico-Regular.woff2 └── index.css /App/beep.js: -------------------------------------------------------------------------------- 1 | a = new AudioContext() // browsers limit the number of concurrent audio contexts, so you better re-use'em 2 | 3 | function beep(vol, freq, duration) { 4 | console.log({ vol, freq, duration }) 5 | v = a.createOscillator() 6 | u = a.createGain() 7 | v.connect(u) 8 | v.frequency.value = freq 9 | v.type = "square" 10 | u.connect(a.destination) 11 | u.gain.value = vol * 0.01 12 | v.start(a.currentTime) 13 | v.stop(a.currentTime + duration * 0.001) 14 | } -------------------------------------------------------------------------------- /App/script.js: -------------------------------------------------------------------------------- 1 | let bars = []; 2 | const def = "#fd0081", chng = "#431f91", finished = "#8ef511", selected = "yellow"; 3 | 4 | window.onload = setup(); 5 | async function setup() { 6 | let b = document.getElementById("bars"); 7 | let d = document.getElementById("delay"); 8 | document.getElementById("b").innerText = b.value; 9 | document.getElementById("d").innerText = d.value + "ms"; 10 | 11 | if (bars.length != parseInt(b.value)) { 12 | generateBars(parseInt(b.value)); 13 | } 14 | } 15 | 16 | 17 | function reset() { 18 | location.reload(); 19 | } 20 | 21 | 22 | function Disable_The_Input() { 23 | let x = document.getElementsByTagName("input"); 24 | for (let i = 0; i < x.length; i++) 25 | x[i].disabled = true; 26 | return parseInt(document.getElementById("delay").value); 27 | } 28 | 29 | 30 | function Finished_Sorting() { 31 | let x = document.getElementsByClassName("bar"); 32 | for (let i = 0; i < x.length; i++) 33 | x[i].style.backgroundColor = finished; 34 | x = document.getElementsByTagName("input"); 35 | for (let i = 0; i < x.length; i++) 36 | x[i].disabled = false; 37 | 38 | } 39 | 40 | 41 | function generateBars(n = -1) { 42 | bars = []; 43 | let container = document.getElementById("container"); 44 | n = n < 0 ? Math.random() * 20 : n; 45 | for (let i = 0; i < n; i++) { 46 | bars.push('
'); 47 | } 48 | container.innerHTML = bars.join(''); 49 | } 50 | 51 | 52 | function Sleep(ms) { 53 | return new Promise(resolve => setTimeout(resolve, ms)); 54 | } 55 | 56 | function MapRange(value, in_min, in_max, out_min, out_max) { 57 | return (value - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; 58 | } 59 | //=============================== Sorting Algorithms ==================================// 60 | 61 | 62 | // 1 63 | // SELECTION SORT 64 | 65 | // SelectionSort() : Implementation of selection sort algorithm. O(n^2) 66 | async function SelectionSort() { 67 | let delay = Disable_The_Input(); 68 | 69 | let container = document.getElementById("container"); 70 | for (let i = 0; i < bars.length; i++) { 71 | let mn_ind = i; 72 | let curr_id = bars[i].split('id="')[1].split('"')[0]; 73 | document.getElementById(curr_id).style.backgroundColor = selected; 74 | let sound = MapRange(document.getElementById(curr_id).style.height.split('%')[0], 2, 100, 500, 1000); 75 | beep(100, sound, delay) 76 | for (let j = i + 1; j < bars.length; j++) { 77 | let nxt_ele = bars[j].split('id="')[1].split('"')[0]; 78 | document.getElementById(nxt_ele).style.backgroundColor = chng; 79 | let a = parseInt(bars[mn_ind].split(/[:%]/)[1]); 80 | let b = parseInt(bars[j].split(/[:%]/)[1]); 81 | if (a > b) mn_ind = j; 82 | await Sleep(delay / 5.0); 83 | document.getElementById(nxt_ele).style.backgroundColor = def; 84 | } 85 | 86 | let nxt_ele = bars[mn_ind].split('id="')[1].split('"')[0]; 87 | document.getElementById(nxt_ele).style.backgroundColor = selected; 88 | await Sleep(2 * delay / 5.0); 89 | 90 | let tmp = bars[mn_ind]; 91 | bars[mn_ind] = bars[i]; 92 | bars[i] = tmp; 93 | 94 | container.innerHTML = bars.join(''); 95 | await Sleep(2 * delay / 5.0); 96 | document.getElementById(curr_id).style.backgroundColor = def; 97 | document.getElementById(nxt_ele).style.backgroundColor = def; 98 | } 99 | Finished_Sorting(); 100 | } 101 | 102 | 103 | 104 | 105 | 106 | 107 | // 2 108 | // BUBBLE SORT 109 | 110 | // BubbleSort() : Implementation of bubble sort algorithm. O(n^2) 111 | async function BubbleSort() { 112 | let delay = Disable_The_Input(); 113 | let container = document.getElementById("container"); 114 | 115 | for (let i = 0; i < bars.length - 1; i++) { 116 | let has_swap = false; 117 | for (let j = 0; j < bars.length - i - 1; j++) { 118 | let curr_id = bars[j].split('id="')[1].split('"')[0]; 119 | let nxt_ele = bars[j + 1].split('id="')[1].split('"')[0]; 120 | 121 | document.getElementById(curr_id).style.backgroundColor = selected; 122 | let sound = MapRange(document.getElementById(curr_id).style.height.split('%')[0], 2, 100, 500, 1000); 123 | beep(100, sound, delay) 124 | document.getElementById(nxt_ele).style.backgroundColor = chng; 125 | await Sleep(delay / 2); 126 | let a = parseInt(bars[j].split(/[:%]/)[1]); 127 | let b = parseInt(bars[j + 1].split(/[:%]/)[1]); 128 | if (a > b) { 129 | has_swap = true; 130 | 131 | let t = bars[j]; 132 | bars[j] = bars[j + 1]; 133 | bars[j + 1] = t; 134 | 135 | container.innerHTML = bars.join(''); 136 | } 137 | document.getElementById(curr_id).style.backgroundColor = selected; 138 | document.getElementById(nxt_ele).style.backgroundColor = chng; 139 | await Sleep(delay / 2.0); 140 | document.getElementById(curr_id).style.backgroundColor = def; 141 | document.getElementById(nxt_ele).style.backgroundColor = def; 142 | } 143 | if (has_swap == false) break; 144 | } 145 | Finished_Sorting(); 146 | } 147 | 148 | 149 | 150 | 151 | 152 | // 3 153 | // INSERTION SORT 154 | 155 | // InsertionSort() : Implementation of inserion sort algorithm. O(n^2) 156 | async function InsertionSort() { 157 | let delay = Disable_The_Input(); 158 | let container = document.getElementById("container"); 159 | for (let i = 1; i < bars.length; i++) { 160 | let j = i - 1; 161 | let key = bars[i]; 162 | let curr_id = key.split('id="')[1].split('"')[0]; 163 | let nxt_ele = bars[j].split('id="')[1].split('"')[0]; 164 | document.getElementById(curr_id).style.backgroundColor = selected; 165 | let sound = MapRange(document.getElementById(curr_id).style.height.split('%')[0], 2, 100, 500, 1000); 166 | beep(100, sound, delay) 167 | while (j >= 0 && parseInt(bars[j].split(/[:%]/)[1]) > parseInt(key.split(/[:%]/)[1])) { 168 | document.getElementById(nxt_ele).style.backgroundColor = def; 169 | nxt_ele = bars[j].split('id="')[1].split('"')[0]; 170 | document.getElementById(nxt_ele).style.backgroundColor = chng; 171 | await Sleep(delay); 172 | bars[j + 1] = bars[j]; 173 | j--; 174 | } 175 | 176 | bars[j + 1] = key; 177 | container.innerHTML = bars.join(''); 178 | document.getElementById(curr_id).style.backgroundColor = selected; 179 | document.getElementById(nxt_ele).style.backgroundColor = chng; 180 | await Sleep(delay * 3.0 / 5); 181 | document.getElementById(curr_id).style.backgroundColor = def; 182 | document.getElementById(nxt_ele).style.backgroundColor = def; 183 | } 184 | Finished_Sorting(); 185 | } 186 | 187 | 188 | 189 | // 4 190 | // MERGE SORT 191 | // Slide_down() : Places bars[r] at lth position by sliding other bars to the right. 192 | function Slide_down(l, r) { 193 | let temp = bars[r]; 194 | for (let i = r - 1; i >= l; i--) { 195 | bars[i + 1] = bars[i]; 196 | } 197 | bars[l] = temp; 198 | } 199 | 200 | 201 | async function merge(l, m, r, d) { 202 | let y = l; 203 | let i = l; 204 | let j = m + 1; 205 | 206 | while (i < j && j <= r) { 207 | let curr_id = bars[j].split('id="')[1].split('"')[0]; 208 | let nxt_ele = bars[i].split('id="')[1].split('"')[0]; 209 | document.getElementById(curr_id).style.backgroundColor = selected; 210 | document.getElementById(nxt_ele).style.backgroundColor = chng; 211 | let a = parseInt(bars[j].split(/[:%]/)[1]); 212 | let b = parseInt(bars[i].split(/[:%]/)[1]); 213 | 214 | if (a > b) i++; 215 | else { 216 | Slide_down(i, j); 217 | i++; j++; 218 | } 219 | await Sleep(d / 2.0); 220 | container.innerHTML = bars.join(''); 221 | document.getElementById(curr_id).style.backgroundColor = selected; 222 | document.getElementById(nxt_ele).style.backgroundColor = chng; 223 | let sound = MapRange(document.getElementById(curr_id).style.height.split('%')[0], 2, 100, 500, 1000); 224 | beep(100, sound, d) 225 | await Sleep(d / 2.0); 226 | document.getElementById(curr_id).style.backgroundColor = def; 227 | document.getElementById(nxt_ele).style.backgroundColor = def; 228 | sound = MapRange(document.getElementById(curr_id).style.height.split('%')[0], 2, 100, 500, 1000); 229 | beep(100, sound, d) 230 | } 231 | } 232 | 233 | 234 | async function mergeSort(l, r, d) { 235 | if (l < r) { 236 | let m = parseInt(l + (r - l) / 2); 237 | await mergeSort(l, m, d); 238 | await mergeSort(m + 1, r, d); 239 | await merge(l, m, r, d); 240 | } 241 | } 242 | 243 | 244 | async function MergeSort() { 245 | let delay = Disable_The_Input(); 246 | await mergeSort(0, bars.length - 1, delay); 247 | Finished_Sorting(); 248 | } 249 | 250 | 251 | 252 | 253 | // 5 254 | // QUICK SORT 255 | // Partition(): Places the (r)th bar at the correct position 256 | async function Partition(l, r, d) { 257 | let i = l - 1; 258 | let j = l; 259 | let id = bars[r].split('id="')[1].split('"')[0]; 260 | document.getElementById(id).style.backgroundColor = selected; 261 | for (j = l; j < r; j++) { 262 | let a = parseInt(bars[j].split(/[:%]/)[1]); 263 | let b = parseInt(bars[r].split(/[:%]/)[1]); 264 | if (a < b) { 265 | i++; 266 | let curr_id = bars[i].split('id="')[1].split('"')[0]; 267 | let nxt_ele = bars[j].split('id="')[1].split('"')[0]; 268 | document.getElementById(curr_id).style.backgroundColor = chng; 269 | document.getElementById(nxt_ele).style.backgroundColor = chng; 270 | 271 | let temp = bars[i]; 272 | bars[i] = bars[j]; 273 | bars[j] = temp; 274 | 275 | await Sleep(d / 3.0); 276 | container.innerHTML = bars.join(''); 277 | document.getElementById(curr_id).style.backgroundColor = chng; 278 | document.getElementById(nxt_ele).style.backgroundColor = chng; 279 | document.getElementById(id).style.backgroundColor = selected; 280 | let sound = MapRange(document.getElementById(curr_id).style.height.split('%')[0], 2, 100, 500, 1000); 281 | beep(100, sound, d) 282 | await Sleep(d / 3.0) 283 | document.getElementById(curr_id).style.backgroundColor = def; 284 | document.getElementById(nxt_ele).style.backgroundColor = def; 285 | } 286 | } 287 | 288 | let temp = bars[i + 1]; 289 | bars[i + 1] = bars[r]; 290 | bars[r] = temp; 291 | 292 | container.innerHTML = bars.join(' '); 293 | document.getElementById(id).style.backgroundColor = selected; 294 | await Sleep(d / 3.0); 295 | document.getElementById(id).style.backgroundColor = def; 296 | return i + 1; 297 | } 298 | 299 | 300 | async function quickSort(l, r, d) { 301 | if (l < r) { 302 | let p = await Partition(l, r, d); 303 | await quickSort(l, p - 1, d); 304 | await quickSort(p + 1, r, d); 305 | } 306 | } 307 | 308 | 309 | async function QuickSort() { 310 | let delay = Disable_The_Input(); 311 | await quickSort(0, bars.length - 1, delay); 312 | Finished_Sorting(); 313 | } 314 | 315 | 316 | 317 | 318 | // 6 319 | // HEAP SORT 320 | // Heapfiy(): Creates a max heap. 321 | async function Heapfiy(n, i, d) { 322 | let largest = i; 323 | let l = 2 * i + 1; // lft 324 | let r = 2 * i + 2; // rgt 325 | let curr_id = bars[i].split('id="')[1].split('"')[0]; 326 | let nxt_ele; 327 | let id3; 328 | 329 | document.getElementById(curr_id).style.backgroundColor = selected; 330 | if (r < n) { 331 | id3 = bars[r].split('id="')[1].split('"')[0]; 332 | document.getElementById(id3).style.backgroundColor = chng; 333 | } 334 | if (l < n) { 335 | nxt_ele = bars[l].split('id="')[1].split('"')[0]; 336 | document.getElementById(nxt_ele).style.backgroundColor = chng; 337 | } 338 | await Sleep(d / 3.0) 339 | if (l < n && parseInt(bars[l].split(/[:%]/)[1]) > parseInt(bars[largest].split(/[:%]/)[1])) 340 | largest = l; 341 | if (r < n && parseInt(bars[r].split(/[:%]/)[1]) > parseInt(bars[largest].split(/[:%]/)[1])) 342 | largest = r; 343 | 344 | if (largest != i) { 345 | let t = bars[i]; bars[i] = bars[largest]; bars[largest] = t; 346 | container.innerHTML = bars.join(' '); 347 | document.getElementById(curr_id).style.backgroundColor = selected; 348 | let sound = MapRange(document.getElementById(curr_id).style.height.split('%')[0], 2, 100, 500, 1000); 349 | beep(100, sound, d) 350 | if (r < n) document.getElementById(id3).style.backgroundColor = chng; 351 | if (l < n) document.getElementById(nxt_ele).style.backgroundColor = chng; 352 | await Sleep(d / 3.0) 353 | container.innerHTML = bars.join(' '); 354 | await Heapfiy(n, largest, d); 355 | } 356 | container.innerHTML = bars.join(' '); 357 | } 358 | 359 | 360 | async function HeapSort() { 361 | let delay = Disable_The_Input(); 362 | let n = bars.length; 363 | for (let i = n / 2 - 1; i >= 0; i--) // Build the heap 364 | await Heapfiy(n, i, delay); 365 | 366 | for (let i = n - 1; i >= 0; i--) { 367 | let t = bars[0]; // Swaping 368 | bars[0] = bars[i]; 369 | bars[i] = t; 370 | 371 | container.innerHTML = bars.join(' '); 372 | await Heapfiy(i, 0, delay); 373 | } 374 | Finished_Sorting(); 375 | } 376 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Abdallah Hemdan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |2 | 3 |  4 | 5 | 6 |
7 |