@@ -67,11 +67,16 @@ function estimateSortingTime() { |
| 67 | case 'heap': | 67 | case 'heap': |
| 68 | return baseTime * Math.log2(array.length) * 2; | 68 | return baseTime * Math.log2(array.length) * 2; |
| 69 | case 'shell': | 69 | case 'shell': |
| | 70 | + case 'comb': |
| 70 | return baseTime * array.length * 0.3; | 71 | return baseTime * array.length * 0.3; |
| 71 | case 'radix': | 72 | case 'radix': |
| 72 | return baseTime * 3; | 73 | return baseTime * 3; |
| 73 | case 'gnome': | 74 | case 'gnome': |
| 74 | return baseTime * array.length * 0.7; | 75 | return baseTime * array.length * 0.7; |
| | 76 | + case 'pancake': |
| | 77 | + return baseTime * array.length * 0.8; |
| | 78 | + case 'bitonic': |
| | 79 | + return baseTime * Math.log2(array.length) * Math.log2(array.length); |
| 75 | case 'bogo': | 80 | case 'bogo': |
| 76 | return baseTime * 10; // Who knows! | 81 | return baseTime * 10; // Who knows! |
| 77 | default: | 82 | default: |
@@ -339,6 +344,15 @@ async function startSort() { |
| 339 | case 'bogo': | 344 | case 'bogo': |
| 340 | await bogoSort(); | 345 | await bogoSort(); |
| 341 | break; | 346 | break; |
| | 347 | + case 'comb': |
| | 348 | + await combSort(); |
| | 349 | + break; |
| | 350 | + case 'pancake': |
| | 351 | + await pancakeSort(); |
| | 352 | + break; |
| | 353 | + case 'bitonic': |
| | 354 | + await bitonicSort(); |
| | 355 | + break; |
| 342 | } | 356 | } |
| 343 | | 357 | |
| 344 | // Stop slide whistle and play zoot | 358 | // Stop slide whistle and play zoot |
@@ -763,6 +777,138 @@ function markAllSorted() { |
| 763 | }); | 777 | }); |
| 764 | } | 778 | } |
| 765 | | 779 | |
| | 780 | +// Comb Sort (improved Bubble Sort with gap) |
| | 781 | +async function combSort() { |
| | 782 | + let gap = array.length; |
| | 783 | + let shrink = 1.3; |
| | 784 | + let sorted = false; |
| | 785 | + |
| | 786 | + while (gap > 1 || !sorted) { |
| | 787 | + // Update gap |
| | 788 | + gap = Math.floor(gap / shrink); |
| | 789 | + if (gap < 1) gap = 1; |
| | 790 | + |
| | 791 | + sorted = true; |
| | 792 | + |
| | 793 | + // Single pass with current gap |
| | 794 | + for (let i = 0; i + gap < array.length; i++) { |
| | 795 | + await compare(i, i + gap); |
| | 796 | + if (array[i] > array[i + gap]) { |
| | 797 | + await swap(i, i + gap); |
| | 798 | + sorted = false; |
| | 799 | + } |
| | 800 | + } |
| | 801 | + |
| | 802 | + // Mark sorted elements when gap is 1 (final pass) |
| | 803 | + if (gap === 1 && sorted) { |
| | 804 | + for (let i = 0; i < array.length; i++) { |
| | 805 | + document.querySelectorAll('.bar-row')[i].classList.add('sorted'); |
| | 806 | + await sleep(getDelay() / 4); |
| | 807 | + } |
| | 808 | + } |
| | 809 | + } |
| | 810 | +} |
| | 811 | + |
| | 812 | +// Pancake Sort (flip sort) |
| | 813 | +async function pancakeSort() { |
| | 814 | + for (let curr_size = array.length; curr_size > 1; curr_size--) { |
| | 815 | + // Find index of maximum element in unsorted portion |
| | 816 | + let maxIdx = 0; |
| | 817 | + for (let i = 1; i < curr_size; i++) { |
| | 818 | + await compare(i, maxIdx); |
| | 819 | + if (array[i] > array[maxIdx]) { |
| | 820 | + maxIdx = i; |
| | 821 | + } |
| | 822 | + } |
| | 823 | + |
| | 824 | + // Move maximum element to end if it's not already there |
| | 825 | + if (maxIdx !== curr_size - 1) { |
| | 826 | + // Flip to move max to beginning |
| | 827 | + if (maxIdx !== 0) { |
| | 828 | + await flip(maxIdx + 1); |
| | 829 | + } |
| | 830 | + |
| | 831 | + // Flip to move max to correct position |
| | 832 | + await flip(curr_size); |
| | 833 | + } |
| | 834 | + |
| | 835 | + document.querySelectorAll('.bar-row')[curr_size - 1].classList.add('sorted'); |
| | 836 | + } |
| | 837 | + document.querySelectorAll('.bar-row')[0].classList.add('sorted'); |
| | 838 | +} |
| | 839 | + |
| | 840 | +// Helper function for pancake sort - flips array from 0 to n-1 |
| | 841 | +async function flip(n) { |
| | 842 | + let start = 0; |
| | 843 | + let end = n - 1; |
| | 844 | + |
| | 845 | + while (start < end) { |
| | 846 | + await swap(start, end); |
| | 847 | + start++; |
| | 848 | + end--; |
| | 849 | + } |
| | 850 | +} |
| | 851 | + |
| | 852 | +// Bitonic Sort (requires power of 2 array size) |
| | 853 | +async function bitonicSort() { |
| | 854 | + // Adjust array size to nearest power of 2 if needed |
| | 855 | + const originalLength = array.length; |
| | 856 | + const nextPowerOf2 = Math.pow(2, Math.ceil(Math.log2(array.length))); |
| | 857 | + |
| | 858 | + // Pad with large values if necessary |
| | 859 | + while (array.length < nextPowerOf2) { |
| | 860 | + array.push(999); |
| | 861 | + } |
| | 862 | + renderArray(); |
| | 863 | + |
| | 864 | + // Start the bitonic sort |
| | 865 | + await bitonicSortRecursive(0, array.length, true); |
| | 866 | + |
| | 867 | + // Remove padding if we added any |
| | 868 | + if (array.length > originalLength) { |
| | 869 | + array.length = originalLength; |
| | 870 | + renderArray(); |
| | 871 | + } |
| | 872 | + |
| | 873 | + // Mark all as sorted |
| | 874 | + for (let i = 0; i < originalLength; i++) { |
| | 875 | + document.querySelectorAll('.bar-row')[i].classList.add('sorted'); |
| | 876 | + } |
| | 877 | +} |
| | 878 | + |
| | 879 | +async function bitonicSortRecursive(lo, cnt, dir) { |
| | 880 | + if (cnt > 1) { |
| | 881 | + let k = Math.floor(cnt / 2); |
| | 882 | + |
| | 883 | + // Sort in ascending order |
| | 884 | + await bitonicSortRecursive(lo, k, true); |
| | 885 | + |
| | 886 | + // Sort in descending order |
| | 887 | + await bitonicSortRecursive(lo + k, k, false); |
| | 888 | + |
| | 889 | + // Merge the whole sequence |
| | 890 | + await bitonicMerge(lo, cnt, dir); |
| | 891 | + } |
| | 892 | +} |
| | 893 | + |
| | 894 | +async function bitonicMerge(lo, cnt, dir) { |
| | 895 | + if (cnt > 1) { |
| | 896 | + let k = Math.floor(cnt / 2); |
| | 897 | + |
| | 898 | + for (let i = lo; i < lo + k; i++) { |
| | 899 | + await compare(i, i + k); |
| | 900 | + |
| | 901 | + // Swap if needed based on direction |
| | 902 | + if ((array[i] > array[i + k]) === dir) { |
| | 903 | + await swap(i, i + k); |
| | 904 | + } |
| | 905 | + } |
| | 906 | + |
| | 907 | + await bitonicMerge(lo, k, dir); |
| | 908 | + await bitonicMerge(lo + k, k, dir); |
| | 909 | + } |
| | 910 | +} |
| | 911 | + |
| 766 | // Initialize | 912 | // Initialize |
| 767 | generateArray(); | 913 | generateArray(); |
| 768 | document.querySelector('.algorithm-btn').click(); | 914 | document.querySelector('.algorithm-btn').click(); |