Skip to content

Commit 712868e

Browse files
committed
Re work, fix bugs, names etc.
1 parent d32e435 commit 712868e

File tree

2 files changed

+118
-139
lines changed

2 files changed

+118
-139
lines changed
Lines changed: 118 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -1,75 +1,73 @@
11
package com.thealgorithms.sorts;
22

33
import java.util.ArrayList;
4+
import java.util.Arrays;
5+
import java.util.Collections;
46

57
/**
68
* Wikipedia: https://en.wikipedia.org/wiki/Smoothsort
79
*/
8-
public final class SmoothSort {
10+
public final class SmoothSort implements SortAlgorithm {
911

10-
private SmoothSort() {
12+
public SmoothSort() {
1113
}
1214

13-
public static Integer[] getLeonardoNumbers() {
15+
private static Integer[] getLeonardoNumbers() {
1416
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,
1517
204668309, 331160281, 535828591};
1618

1719
return leonardoNumbers;
1820
}
1921

20-
public static Integer[] smoothSort(Integer[] array) {
22+
private static <T extends Comparable<T>> void smoothSort(T[] array) {
2123
int length = array.length;
2224
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
2426

2527
while (leonardoHeapSize < length) {
2628
// if two trees with consequtive level
2729
// combine them to get new tree
2830
// else if there is no Level 1, add the node as level 1
2931
// else add the node as Level 0
30-
// perform shiftRoot to restore heap property
32+
// perform shiftRoot and restore heap property
3133

32-
Integer[] consecutiveTreeIndices = findConsecutiveLeonardoTrees(leonardoLevels);
34+
Integer[] consecutiveTreeIndices = findConsecutiveLeonardoTreeIndices(leonardoLevelTracker);
3335
if (consecutiveTreeIndices[0] != -1) {
3436
// 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);
4042
} else {
41-
leonardoLevels = leonardoLevels | (1 << 0);
43+
leonardoLevelTracker = leonardoLevelTracker | (1 << 0);
4244
}
43-
4445
leonardoHeapSize++;
45-
array = shiftRoot(leonardoLevels, leonardoHeapSize, array);
46+
shiftRootAndRestoreHeap(leonardoLevelTracker, leonardoHeapSize, array);
4647
}
4748

48-
// Now our Leonardo heap is fully ready, start extracting the max
4949
while (leonardoHeapSize > 0) {
5050
// destroy the current level
5151
// if level is not L1 or L0
5252
// create two smaller sublevels
53-
// perform shiftRoot to restore heap property
53+
// perform shiftRoot and restore heap property
5454

55-
int lastTreeLevel = getRightMostTree(leonardoLevels); // getting the right most tree
55+
int lastTreeLevel = getRightMostTree(leonardoLevelTracker); // getting the right most tree
5656

57-
leonardoLevels = leonardoLevels & ~(1 << lastTreeLevel);
57+
leonardoLevelTracker = leonardoLevelTracker & ~(1 << lastTreeLevel);
5858
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);
6161
}
6262

6363
leonardoHeapSize--;
64-
array = shiftRoot(leonardoLevels, leonardoHeapSize, array);
64+
shiftRootAndRestoreHeap(leonardoLevelTracker, leonardoHeapSize, array);
6565
}
66-
67-
return array;
6866
}
6967

70-
public static int getRightMostTree(int leonardoLevels) {
68+
private static int getRightMostTree(int leonardoLevelTracker) {
7169
// Isolate the rightmost set bit
72-
int isolatedBit = leonardoLevels & -leonardoLevels;
70+
int isolatedBit = leonardoLevelTracker & -leonardoLevelTracker;
7371
int position = 0;
7472

7573
while (isolatedBit > 1) {
@@ -80,14 +78,14 @@ public static int getRightMostTree(int leonardoLevels) {
8078
return position;
8179
}
8280

83-
public static Integer[] findConsecutiveLeonardoTrees(int num) {
81+
private static Integer[] findConsecutiveLeonardoTreeIndices(int num) {
8482
int prevOneIndex = -1;
85-
int currentBit;
83+
int currentLevel;
8684

8785
Integer[] answer = new Integer[] {-1, -1};
8886
for (int i = 0; num > 0; i++) {
89-
currentBit = num & 1;
90-
if (currentBit == 1) {
87+
currentLevel = num & 1;
88+
if (currentLevel == 1) {
9189
if (prevOneIndex != -1) {
9290
answer[0] = prevOneIndex;
9391
answer[1] = i;
@@ -101,7 +99,7 @@ public static Integer[] findConsecutiveLeonardoTrees(int num) {
10199
return answer;
102100
}
103101

104-
public static Integer[] findAllLeonardoTrees(int num) {
102+
private static Integer[] findAllLeonardoTreeIndices(int num) {
105103
int setBitCount = 0;
106104
for (int i = 0; i < Integer.SIZE; i++) {
107105
if ((num & (1 << i)) != 0) {
@@ -119,86 +117,115 @@ public static Integer[] findAllLeonardoTrees(int num) {
119117
return setBitIndexes;
120118
}
121119

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+
123122
if (leonardoHeapSize == 0) {
124-
return array;
123+
return;
125124
}
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]];
136137
}
137138

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);
141149
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);
153163
}
154164
} else {
155165
// 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;
161174
}
162175

163-
j--;
176+
currentRootNodeIndex = rootNodeIndices.get(j);
177+
prevRootNodeIndex = rootNodeIndices.get(j - 1);
164178
}
165179
}
166180

167-
array = maxHeapify(rootNodeIndexForHeapify, treeSizeForHeapify, array);
168-
return array;
181+
maxHeapifyLeonardoTree(rootNodeIndexForHeapify, leonardoTreeLevelforHeapify, array); // for the last tree if needed
169182
}
170183

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+
}
174189

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
179194

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.
182198
}
183199

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);
200221
}
201222
}
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;
203230
}
204231
}

src/test/java/com/thealgorithms/sorts/SmoothSortTest.java

Lines changed: 0 additions & 48 deletions
This file was deleted.

0 commit comments

Comments
 (0)