1
1
package com .thealgorithms .sorts ;
2
2
3
3
import java .util .ArrayList ;
4
+ import java .util .Arrays ;
5
+ import java .util .Collections ;
4
6
5
7
/**
6
8
* Wikipedia: https://en.wikipedia.org/wiki/Smoothsort
7
9
*/
8
- public final class SmoothSort {
10
+ public final class SmoothSort implements SortAlgorithm {
9
11
10
- private SmoothSort () {
12
+ public SmoothSort () {
11
13
}
12
14
13
- public static Integer [] getLeonardoNumbers () {
15
+ private static Integer [] getLeonardoNumbers () {
14
16
Integer [] leonardoNumbers = {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 , 1405773 , 18454929 , 29860703 , 48315633 , 78176337 , 126491971 ,
15
17
204668309 , 331160281 , 535828591 };
16
18
17
19
return leonardoNumbers ;
18
20
}
19
21
20
- public static Integer [] smoothSort (Integer [] array ) {
22
+ private static < T extends Comparable < T >> void smoothSort (T [] array ) {
21
23
int length = array .length ;
22
24
int leonardoHeapSize = 0 ; // start with size 0
23
- int leonardoLevels = 0 ; // No leonardo tree present initially
25
+ int leonardoLevelTracker = 0 ; // No leonardo tree present initially
24
26
25
27
while (leonardoHeapSize < length ) {
26
28
// if two trees with consequtive level
27
29
// combine them to get new tree
28
30
// else if there is no Level 1, add the node as level 1
29
31
// else add the node as Level 0
30
- // perform shiftRoot to restore heap property
32
+ // perform shiftRoot and restore heap property
31
33
32
- Integer [] consecutiveTreeIndices = findConsecutiveLeonardoTrees ( leonardoLevels );
34
+ Integer [] consecutiveTreeIndices = findConsecutiveLeonardoTreeIndices ( leonardoLevelTracker );
33
35
if (consecutiveTreeIndices [0 ] != -1 ) {
34
36
// if 0th or 1st index is -1 that implies there are no concequtive trees
35
- leonardoLevels = leonardoLevels & ~(1 << consecutiveTreeIndices [0 ]);
36
- leonardoLevels = leonardoLevels & ~(1 << consecutiveTreeIndices [1 ]);
37
- leonardoLevels = leonardoLevels | (1 << consecutiveTreeIndices [1 ] + 1 );
38
- } else if ((leonardoLevels & 2 ) == 0 ) {
39
- leonardoLevels = leonardoLevels | (1 << 1 );
37
+ leonardoLevelTracker = leonardoLevelTracker & ~(1 << consecutiveTreeIndices [0 ]);
38
+ leonardoLevelTracker = leonardoLevelTracker & ~(1 << consecutiveTreeIndices [1 ]);
39
+ leonardoLevelTracker = leonardoLevelTracker | (1 << consecutiveTreeIndices [1 ] + 1 );
40
+ } else if ((leonardoLevelTracker & 2 ) == 0 ) {
41
+ leonardoLevelTracker = leonardoLevelTracker | (1 << 1 );
40
42
} else {
41
- leonardoLevels = leonardoLevels | (1 << 0 );
43
+ leonardoLevelTracker = leonardoLevelTracker | (1 << 0 );
42
44
}
43
-
44
45
leonardoHeapSize ++;
45
- array = shiftRoot ( leonardoLevels , leonardoHeapSize , array );
46
+ shiftRootAndRestoreHeap ( leonardoLevelTracker , leonardoHeapSize , array );
46
47
}
47
48
48
- // Now our Leonardo heap is fully ready, start extracting the max
49
49
while (leonardoHeapSize > 0 ) {
50
50
// destroy the current level
51
51
// if level is not L1 or L0
52
52
// create two smaller sublevels
53
- // perform shiftRoot to restore heap property
53
+ // perform shiftRoot and restore heap property
54
54
55
- int lastTreeLevel = getRightMostTree (leonardoLevels ); // getting the right most tree
55
+ int lastTreeLevel = getRightMostTree (leonardoLevelTracker ); // getting the right most tree
56
56
57
- leonardoLevels = leonardoLevels & ~(1 << lastTreeLevel );
57
+ leonardoLevelTracker = leonardoLevelTracker & ~(1 << lastTreeLevel );
58
58
if (lastTreeLevel != 0 && lastTreeLevel != 1 ) {
59
- leonardoLevels = leonardoLevels | (1 << lastTreeLevel - 1 );
60
- leonardoLevels = leonardoLevels | (1 << lastTreeLevel - 2 );
59
+ leonardoLevelTracker = leonardoLevelTracker | (1 << lastTreeLevel - 1 );
60
+ leonardoLevelTracker = leonardoLevelTracker | (1 << lastTreeLevel - 2 );
61
61
}
62
62
63
63
leonardoHeapSize --;
64
- array = shiftRoot ( leonardoLevels , leonardoHeapSize , array );
64
+ shiftRootAndRestoreHeap ( leonardoLevelTracker , leonardoHeapSize , array );
65
65
}
66
-
67
- return array ;
68
66
}
69
67
70
- public static int getRightMostTree (int leonardoLevels ) {
68
+ private static int getRightMostTree (int leonardoLevelTracker ) {
71
69
// Isolate the rightmost set bit
72
- int isolatedBit = leonardoLevels & -leonardoLevels ;
70
+ int isolatedBit = leonardoLevelTracker & -leonardoLevelTracker ;
73
71
int position = 0 ;
74
72
75
73
while (isolatedBit > 1 ) {
@@ -80,14 +78,14 @@ public static int getRightMostTree(int leonardoLevels) {
80
78
return position ;
81
79
}
82
80
83
- public static Integer [] findConsecutiveLeonardoTrees (int num ) {
81
+ private static Integer [] findConsecutiveLeonardoTreeIndices (int num ) {
84
82
int prevOneIndex = -1 ;
85
- int currentBit ;
83
+ int currentLevel ;
86
84
87
85
Integer [] answer = new Integer [] {-1 , -1 };
88
86
for (int i = 0 ; num > 0 ; i ++) {
89
- currentBit = num & 1 ;
90
- if (currentBit == 1 ) {
87
+ currentLevel = num & 1 ;
88
+ if (currentLevel == 1 ) {
91
89
if (prevOneIndex != -1 ) {
92
90
answer [0 ] = prevOneIndex ;
93
91
answer [1 ] = i ;
@@ -101,7 +99,7 @@ public static Integer[] findConsecutiveLeonardoTrees(int num) {
101
99
return answer ;
102
100
}
103
101
104
- public static Integer [] findAllLeonardoTrees (int num ) {
102
+ private static Integer [] findAllLeonardoTreeIndices (int num ) {
105
103
int setBitCount = 0 ;
106
104
for (int i = 0 ; i < Integer .SIZE ; i ++) {
107
105
if ((num & (1 << i )) != 0 ) {
@@ -119,86 +117,115 @@ public static Integer[] findAllLeonardoTrees(int num) {
119
117
return setBitIndexes ;
120
118
}
121
119
122
- public static Integer [] shiftRoot (int lenardoLevels , int leonardoHeapSize , Integer [] array ) {
120
+ private static <T extends Comparable <T >> void shiftRootAndRestoreHeap (int lenardoLevelTracker , int leonardoHeapSize , T [] array ) {
121
+
123
122
if (leonardoHeapSize == 0 ) {
124
- return array ;
123
+ return ;
125
124
}
126
- Integer [] currentLeonardoTrees = findAllLeonardoTrees (lenardoLevels );
127
- Integer [] leonardoNumbers = getLeonardoNumbers ();
128
- int prevTreeSizeCumulative = 0 ;
129
- ArrayList <Integer > treeSizeList = new ArrayList <Integer >();
130
- ArrayList <Integer > rootNodeIndex = new ArrayList <Integer >();
131
- for (int i = currentLeonardoTrees .length - 1 ; i >= 0 ; i --) {
132
- int currentTreeSize = leonardoNumbers [currentLeonardoTrees [i ]];
133
- treeSizeList .add (currentTreeSize );
134
- rootNodeIndex .add (prevTreeSizeCumulative + currentTreeSize - 1 );
135
- prevTreeSizeCumulative = prevTreeSizeCumulative + currentTreeSize ;
125
+
126
+ Integer [] currentLeonardoTreeLevels = findAllLeonardoTreeIndices (lenardoLevelTracker );
127
+ int previousTreeSizeCumulative = 0 ;
128
+ ArrayList <Integer > rootNodeIndices = new ArrayList <Integer >();
129
+ Collections .reverse (Arrays .asList (currentLeonardoTreeLevels )); // To get the Levels in decreasing order of levels
130
+
131
+ // The number of roots are going to be same the the number of levels
132
+ // iterate over the currentLeonardoTreeLevels and get roots
133
+
134
+ for (int i = 0 ; i < currentLeonardoTreeLevels .length ; i ++) {
135
+ rootNodeIndices .add (previousTreeSizeCumulative + getLeonardoNumbers ()[currentLeonardoTreeLevels [i ]] - 1 );
136
+ previousTreeSizeCumulative = previousTreeSizeCumulative + getLeonardoNumbers ()[currentLeonardoTreeLevels [i ]];
136
137
}
137
138
138
- int rootNodeIndexForHeapify = rootNodeIndex .getLast (); // default value for heapify
139
- int treeSizeForHeapify = treeSizeList .getLast ();
140
- for (int i = 1 ; i < currentLeonardoTrees .length ; i ++) { // iterate form 1 because there is no left of the left-most tree
139
+ int rootNodeIndexForHeapify = rootNodeIndices .getLast ();
140
+ int leonardoTreeLevelforHeapify = currentLeonardoTreeLevels [currentLeonardoTreeLevels .length - 1 ];
141
+
142
+ for (int i = 0 ; i < rootNodeIndices .size (); i ++) {
143
+ if (i == 0 ) {
144
+ continue ;
145
+ }
146
+
147
+ int currentRootNodeIndex = rootNodeIndices .get (i );
148
+ int prevRootNodeIndex = rootNodeIndices .get (i - 1 );
141
149
int j = i ;
142
- while (j > 0 && array [rootNodeIndex .get (j - 1 )] > array [rootNodeIndex .get (j )]) {
143
- int currentTreeSize = treeSizeList .get (j );
144
- if (currentTreeSize >= 3 ) { // has children
145
- // if greater than each of two children then swap
146
- if (array [rootNodeIndex .get (j - 1 )] > array [rootNodeIndex .get (j ) - 1 ] && array [rootNodeIndex .get (j - 1 )] > array [rootNodeIndex .get (j ) - 2 ]) {
147
- // swap
148
- int temp = array [rootNodeIndex .get (j - 1 )];
149
- array [rootNodeIndex .get (j - 1 )] = array [rootNodeIndex .get (j )];
150
- array [rootNodeIndex .get (j )] = temp ;
151
- rootNodeIndexForHeapify = rootNodeIndex .get (j - 1 );
152
- treeSizeForHeapify = treeSizeList .get (j - 1 );
150
+ while (array [prevRootNodeIndex ].compareTo (array [currentRootNodeIndex ]) > 0 ) {
151
+ int currentLeonardoLevel = currentLeonardoTreeLevels [j ];
152
+ if (currentLeonardoLevel > 1 ) {
153
+ // compare child and swap
154
+
155
+ int indexOfRightChild = rootNodeIndices .get (j ) - 1 ; // right child is of level n-2
156
+ int indexOfLeftChild = rootNodeIndices .get (j ) - 1 - getLeonardoNumbers ()[currentLeonardoLevel - 2 ];
157
+ if (array [prevRootNodeIndex ].compareTo (array [indexOfRightChild ]) > 0 && array [prevRootNodeIndex ].compareTo (array [indexOfLeftChild ]) > 0 ) {
158
+ swap (array , prevRootNodeIndex , currentRootNodeIndex );
159
+ rootNodeIndexForHeapify = prevRootNodeIndex ;
160
+ leonardoTreeLevelforHeapify = currentLeonardoTreeLevels [j - 1 ];
161
+ } else {
162
+ maxHeapifyLeonardoTree (currentRootNodeIndex , currentLeonardoLevel , array );
153
163
}
154
164
} else {
155
165
// swap
156
- int temp = array [rootNodeIndex .get (j - 1 )];
157
- array [rootNodeIndex .get (j - 1 )] = array [rootNodeIndex .get (j )];
158
- array [rootNodeIndex .get (j )] = temp ;
159
- rootNodeIndexForHeapify = rootNodeIndex .get (j - 1 );
160
- treeSizeForHeapify = treeSizeList .get (j - 1 );
166
+ swap (array , prevRootNodeIndex , currentRootNodeIndex );
167
+ rootNodeIndexForHeapify = prevRootNodeIndex ;
168
+ leonardoTreeLevelforHeapify = currentLeonardoTreeLevels [j - 1 ];
169
+ }
170
+ j = j - 1 ;
171
+ if (j == i - 1 ) {
172
+ maxHeapifyLeonardoTree (rootNodeIndexForHeapify , leonardoTreeLevelforHeapify , array );
173
+ break ;
161
174
}
162
175
163
- j --;
176
+ currentRootNodeIndex = rootNodeIndices .get (j );
177
+ prevRootNodeIndex = rootNodeIndices .get (j - 1 );
164
178
}
165
179
}
166
180
167
- array = maxHeapify (rootNodeIndexForHeapify , treeSizeForHeapify , array );
168
- return array ;
181
+ maxHeapifyLeonardoTree (rootNodeIndexForHeapify , leonardoTreeLevelforHeapify , array ); // for the last tree if needed
169
182
}
170
183
171
- public static Integer [] maxHeapify (int rootNodeIndex , int treeSizeForHeapify , Integer [] array ) {
172
- int startNodeIndex = rootNodeIndex ;
173
- int endNodeIndex = rootNodeIndex - treeSizeForHeapify + 1 ;
184
+ private static <T > void swap (T [] array , int idx , int idy ) {
185
+ T swap = array [idx ];
186
+ array [idx ] = array [idy ];
187
+ array [idy ] = swap ;
188
+ }
174
189
175
- // This is a heap where the root node is the end index of the array
176
- // The left child node for an element i is 2i - n
177
- // The right child node for an element i is 2i - n - 1
178
- // The parent node is n - 1 - Floor( (n-i-2)/2 )
190
+ private static < T extends Comparable < T >> void maxHeapifyLeonardoTree ( int rootNodeIndex , int currentLeonardoLevel , T [] array ) {
191
+ // A leonardo tree of level n is just 1 node(the root) plus the leonardo tree of n-1 level(left child) plus leonardo tree of n-2 level(right child)
192
+ // To maxheapify a leonardo tree we need to compare the current root and roots of it's left and right subtree
193
+ // We recursively hepify the left and right subtrees using the currentLeonardoLevel
179
194
180
- if (startNodeIndex <= endNodeIndex ) {
181
- return array ;
195
+ // BASE CASE
196
+ if (currentLeonardoLevel == 0 || currentLeonardoLevel == 1 ) {
197
+ return ; // Trees with one node are in already max-heapified.
182
198
}
183
199
184
- for (int i = startNodeIndex ; i >= endNodeIndex ; i --) {
185
- int parentNodeIndex = treeSizeForHeapify + endNodeIndex - 1 - ((treeSizeForHeapify - i + endNodeIndex - 2 ) / 2 );
186
- if ((parentNodeIndex <= rootNodeIndex ) && (parentNodeIndex >= i )) {
187
- int currenNodeIndex = i ;
188
- while (array [currenNodeIndex ] > array [parentNodeIndex ]) {
189
- int temp = array [currenNodeIndex ];
190
- array [currenNodeIndex ] = array [parentNodeIndex ];
191
- array [parentNodeIndex ] = temp ;
192
-
193
- currenNodeIndex = parentNodeIndex ;
194
- parentNodeIndex = treeSizeForHeapify - 1 - ((treeSizeForHeapify - currenNodeIndex - 2 ) / 2 );
195
-
196
- if (currenNodeIndex == rootNodeIndex ) {
197
- break ;
198
- } // reached the root node
199
- }
200
+ int currentRootNodeIndex = rootNodeIndex ;
201
+ int rightChildIndex = rootNodeIndex - 1 ;
202
+ int leftChildIndex = rootNodeIndex - getLeonardoNumbers ()[currentLeonardoLevel - 2 ] - 1 ;
203
+ int childIndexForSwap = -1 ;
204
+
205
+ // maxHeapifyLeonardoTree(rightChildIndex, currentLeonardoLevel - 2, array);
206
+ // maxHeapifyLeonardoTree(leftChildIndex, currentLeonardoLevel - 1, array);
207
+
208
+ if (array [rightChildIndex ].compareTo (array [leftChildIndex ]) >= 0 ) {
209
+ childIndexForSwap = rightChildIndex ;
210
+ } else {
211
+ childIndexForSwap = leftChildIndex ;
212
+ }
213
+
214
+ if (array [childIndexForSwap ].compareTo (array [currentRootNodeIndex ]) > 0 ) {
215
+ // swap(And keep on swapping I guess, I did not implement that which might be causing issue?)
216
+ swap (array , currentRootNodeIndex , childIndexForSwap );
217
+ if (childIndexForSwap == rightChildIndex ) {
218
+ maxHeapifyLeonardoTree (rightChildIndex , currentLeonardoLevel - 2 , array );
219
+ } else { // swap happened with the left child
220
+ maxHeapifyLeonardoTree (leftChildIndex , currentLeonardoLevel - 1 , array );
200
221
}
201
222
}
202
- return array ;
223
+ }
224
+
225
+ @ Override
226
+ public <T extends Comparable <T >> T [] sort (T [] unsorted ) {
227
+ // TODO Auto-generated method stub
228
+ smoothSort (unsorted );
229
+ return unsorted ;
203
230
}
204
231
}
0 commit comments