Skip to content

Commit a18f9b9

Browse files
committed
fix: Final correction for SmoothSort
1 parent 150037f commit a18f9b9

File tree

1 file changed

+59
-39
lines changed

1 file changed

+59
-39
lines changed

src/main/java/com/thealgorithms/sorts/SmoothSort.java

Lines changed: 59 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,16 @@
1919
public final class SmoothSort {
2020
// clang-format off
2121

22-
/**
23-
* Private constructor to prevent instantiation of this utility class.
24-
*/
22+
/** Private constructor to prevent instantiation of this utility class. */
2523
private SmoothSort() {}
2624

2725
// Leonardo numbers: L(0)=1, L(1)=1, L(k)=L(k-1)+L(k-2)+1
2826
private static final int[] LP = {
29-
1, 1, 3, 5, 9, 15, 25, 41, 67, 109, 177, 287, 465, 753, 1219, 1973, 3193, 5167, 8361, 13529, 21891, 35421, 57313, 92735, 150049, 242785, 392835, 635621, 1028457, 1664079, 2692537, 4356617, 7049155, 11405773, 18454929, 29860703, 48315633, 78176337, 126491971, 204668309, 331160281, 535828591, 866988873,
27+
1, 1, 3, 5, 9, 15, 25, 41, 67, 109, 177, 287, 465, 753, 1219, 1973, 3193,
28+
5167, 8361, 13529, 21891, 35421, 57313, 92735, 150049, 242785, 392835,
29+
635621, 1028457, 1664079, 2692537, 4356617, 7049155, 11405773, 18454929,
30+
29860703, 48315633, 78176337, 126491971, 204668309, 331160281, 535828591,
31+
866988873,
3032
};
3133

3234
/**
@@ -41,84 +43,102 @@ public static <T extends Comparable<T>> void sort(T[] arr) {
4143
}
4244
int n = arr.length;
4345

44-
int q = 0; // The order of the rightmost heap
45-
long p = 1; // A bitmask representing the sizes of the heaps
46-
int head = 0; // The head of the list to be sorted
46+
int q = 0; // Order of the rightmost heap
47+
long p = 1; // Bitmask representing heap sizes
48+
int head = 0; // Current index in array
4749

4850
while (head < n) {
4951
if ((p & 3) == 3) {
50-
// Combine the last two heaps
5152
p >>>= 2;
5253
q += 2;
5354
} else {
54-
p >>>= 1;
55-
q = 1;
55+
if ((p & 1) == 0) {
56+
p = (p << 1) | 1;
57+
q = 1;
58+
} else {
59+
p <<= 1;
60+
q = 0;
61+
}
5662
}
57-
p |= 1L << q;
5863

64+
// Prevent out-of-bounds heap building
5965
while (head + LP[q] > n) {
60-
p &= ~(1L << q);
66+
p >>>= 1;
6167
q--;
6268
}
69+
70+
trinkle(arr, head, p, q);
6371
head++;
64-
trinkle(arr, head - 1, p, q);
6572
}
6673

67-
for (head = n - 1; head > 0; head--) {
74+
// Sort the heaps
75+
while (q != 0 || p != 1) {
6876
if (q <= 1) {
69-
p >>>= q;
70-
q = Long.numberOfTrailingZeros(p) + 1;
77+
// Step back through the heaps
78+
while ((p & 1) == 0) {
79+
p >>>= 1;
80+
q++;
81+
}
82+
p >>>= 1;
7183
} else {
7284
p &= ~(1L << q);
7385
q--;
74-
int prevHeapOrder = Long.numberOfTrailingZeros(p) + 1;
75-
sift(arr, head - LP[q], q);
76-
p |= (1L << (prevHeapOrder - 1));
77-
trinkle(arr, head - 1, p, prevHeapOrder);
86+
int right = head - 1;
87+
int left = head - 1 - LP[q];
88+
sift(arr, left + LP[q], q);
89+
sift(arr, right, q);
7890
}
91+
head--;
7992
}
8093
}
8194

8295
private static <T extends Comparable<T>> void trinkle(T[] arr, int head, long p, int q) {
83-
while (q > 0) {
84-
p &= ~(1L << q);
85-
int prevHeapOrder = Long.numberOfTrailingZeros(p) + 1;
86-
87-
if (prevHeapOrder > 0) {
88-
int parent = head - LP[q];
89-
if (arr[parent].compareTo(arr[head]) >= 0) {
90-
break;
91-
}
92-
swap(arr, head, parent);
93-
head = parent;
96+
while (q > 1) {
97+
int parent = head - LP[q];
98+
if (parent < 0) {
99+
return; // prevent negative index
94100
}
95-
q = prevHeapOrder;
101+
102+
if (arr[head].compareTo(arr[parent]) <= 0) {
103+
break;
104+
}
105+
106+
swap(arr, head, parent);
107+
head = parent;
108+
q -= 2;
96109
}
97110
sift(arr, head, q);
98111
}
99112

100113
private static <T extends Comparable<T>> void sift(T[] arr, int head, int order) {
101114
while (order >= 2) {
102115
int rightChild = head - 1;
103-
int leftChild = head - LP[order] + LP[order - 1];
116+
int leftChild = head - 1 - LP[order - 2];
104117

105-
if (arr[head].compareTo(arr[leftChild]) >= 0 && arr[head].compareTo(arr[rightChild]) >= 0) {
118+
if (leftChild < 0 || rightChild < 0) {
119+
return; // safety check
120+
}
121+
122+
int largerChild =
123+
arr[leftChild].compareTo(arr[rightChild]) >= 0 ? leftChild : rightChild;
124+
125+
if (arr[head].compareTo(arr[largerChild]) >= 0) {
106126
break;
107127
}
108128

109-
if (arr[leftChild].compareTo(arr[rightChild]) > 0) {
110-
swap(arr, head, leftChild);
111-
head = leftChild;
129+
swap(arr, head, largerChild);
130+
head = largerChild;
131+
132+
if (largerChild == leftChild) {
112133
order -= 1;
113134
} else {
114-
swap(arr, head, rightChild);
115-
head = rightChild;
116135
order -= 2;
117136
}
118137
}
119138
}
120139

121140
private static <T> void swap(T[] arr, int i, int j) {
141+
if (i == j) return;
122142
T temp = arr[i];
123143
arr[i] = arr[j];
124144
arr[j] = temp;

0 commit comments

Comments
 (0)