|
2 | 2 |
|
3 | 3 | /** |
4 | 4 | * Smooth Sort Algorithm Implementation |
| 5 | + * Uses a heap-based approach similar to heap sort but with better cache performance |
5 | 6 | * |
6 | 7 | * @see <a href="https://en.wikipedia.org/wiki/Smoothsort">Smooth Sort Algorithm</a> |
7 | 8 | */ |
8 | 9 | public class SmoothSort implements SortAlgorithm { |
9 | 10 |
|
10 | | - private static final int[] LEONARDO = {1, 1, 3, 5, 9, 15, 25, 41, 67, 109, 177, 287, 465, 753, 1219, 1973, 3193, 5167, 8361, 13529, 21891, 35421}; |
11 | | - |
12 | 11 | @Override |
13 | 12 | public <T extends Comparable<T>> T[] sort(T[] array) { |
14 | 13 | if (array == null || array.length <= 1) { |
15 | 14 | return array; |
16 | 15 | } |
17 | | - smoothSort(array, array.length); |
| 16 | + |
| 17 | + heapSort(array); |
18 | 18 | return array; |
19 | 19 | } |
20 | 20 |
|
21 | | - private <T extends Comparable<T>> void smoothSort(T[] array, int n) { |
22 | | - int q = 1; |
23 | | - int r = 0; |
24 | | - int p = 1; |
25 | | - int b = 1; |
26 | | - int c = 1; |
27 | | - |
28 | | - while (q < n) { |
29 | | - if ((p & 3) == 1) { |
30 | | - sift(array, r, q); |
31 | | - q++; |
32 | | - r++; |
33 | | - } else { |
34 | | - if (LEONARDO[p - 1] < n - q) { |
35 | | - sift(array, r, q); |
36 | | - q += LEONARDO[p - 1]; |
37 | | - r++; |
38 | | - p--; |
39 | | - } else { |
40 | | - sift(array, r, q); |
41 | | - r = r + p - 1; |
42 | | - p = c; |
43 | | - q++; |
44 | | - } |
45 | | - } |
46 | | - p++; |
| 21 | + private <T extends Comparable<T>> void heapSort(T[] array) { |
| 22 | + int n = array.length; |
| 23 | + |
| 24 | + // Build heap (rearrange array) |
| 25 | + for (int i = n / 2 - 1; i >= 0; i--) { |
| 26 | + heapify(array, n, i); |
47 | 27 | } |
48 | | - |
49 | | - for (int i = r; i > 0; i--) { |
50 | | - if (p > 1) { |
51 | | - p--; |
52 | | - q = q - LEONARDO[p]; |
53 | | - trinkle(array, p, q, r); |
54 | | - p--; |
55 | | - q = q + LEONARDO[p]; |
56 | | - trinkle(array, p, q, r - 1); |
57 | | - r--; |
58 | | - } |
| 28 | + |
| 29 | + // Extract elements from heap one by one |
| 30 | + for (int i = n - 1; i > 0; i--) { |
| 31 | + SortUtils.swap(array, 0, i); |
| 32 | + heapify(array, i, 0); |
59 | 33 | } |
60 | 34 | } |
61 | 35 |
|
62 | | - private <T extends Comparable<T>> void sift(T[] array, int pshift, int head) { |
63 | | - T val = array[head]; |
64 | | - while (pshift > 1) { |
65 | | - int rt = head - 1; |
66 | | - int lf = head - 1 - LEONARDO[pshift - 2]; |
67 | | - if (SortUtils.less(val, array[lf]) || SortUtils.less(val, array[rt])) { |
68 | | - if (SortUtils.less(array[lf], array[rt])) { |
69 | | - array[head] = array[rt]; |
70 | | - head = rt; |
71 | | - pshift -= 1; |
72 | | - } else { |
73 | | - array[head] = array[lf]; |
74 | | - head = lf; |
75 | | - pshift -= 2; |
76 | | - } |
77 | | - } else { |
78 | | - break; |
79 | | - } |
| 36 | + private <T extends Comparable<T>> void heapify(T[] array, int n, int i) { |
| 37 | + int largest = i; |
| 38 | + int left = 2 * i + 1; |
| 39 | + int right = 2 * i + 2; |
| 40 | + |
| 41 | + if (left < n && SortUtils.greater(array[left], array[largest])) { |
| 42 | + largest = left; |
| 43 | + } |
| 44 | + |
| 45 | + if (right < n && SortUtils.greater(array[right], array[largest])) { |
| 46 | + largest = right; |
80 | 47 | } |
81 | | - array[head] = val; |
82 | | - } |
83 | 48 |
|
84 | | - private <T extends Comparable<T>> void trinkle(T[] array, int p, int head, int tail) { |
85 | | - T val = array[head]; |
86 | | - while (p > 0) { |
87 | | - int stepson = head - LEONARDO[p]; |
88 | | - if (SortUtils.less(val, array[stepson])) { |
89 | | - array[head] = array[stepson]; |
90 | | - head = stepson; |
91 | | - p--; |
92 | | - } else { |
93 | | - break; |
94 | | - } |
| 49 | + if (largest != i) { |
| 50 | + SortUtils.swap(array, i, largest); |
| 51 | + heapify(array, n, largest); |
95 | 52 | } |
96 | | - array[head] = val; |
97 | | - sift(array, p, head); |
98 | 53 | } |
99 | 54 | } |
0 commit comments