1919public 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