comments
This commit is contained in:
@ -6,9 +6,12 @@ import de.redstoneunion.git.MrGeorgen.timsort.timsort;
|
||||
|
||||
public class test {
|
||||
public static void main(String[] args) {
|
||||
int[] array = {0, 3, 4, 8, -6, -6, 10, 10, 789, 456, 0, -1, -2, 8, 10, 1, 100, -100, 700, 800, 5};
|
||||
int[] output = timsort.insertionsort(array);
|
||||
System.out.println("Insertionsort test: " + Arrays.toString(output));
|
||||
System.out.println("End result: " + Arrays.toString(timsort.timsort(array)));
|
||||
long startTime = System.nanoTime();
|
||||
int[] test = timsort.timsort(new int[]{20, 1, 573, 34, 281, 201, 0});
|
||||
long endTime = System.nanoTime();
|
||||
|
||||
System.out.println(Arrays.toString(test));
|
||||
long duration = (endTime - startTime);
|
||||
System.out.println("Program executed in " + duration + " nanoseconds.");
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,21 +4,21 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class timsort {
|
||||
public static int[] insertionsort(int[] unsorted) {
|
||||
private static int[] insertionsort(int[] unsorted) {
|
||||
int[] output = new int[unsorted.length];
|
||||
output[0] = unsorted[0];
|
||||
output[0] = unsorted[0]; // copies the first element
|
||||
for(int i = 1; i < unsorted.length; ++i) {
|
||||
int foundIndex = binarySearch(output, unsorted[i], 0, i);
|
||||
for(int j = i; j > foundIndex; --j) {
|
||||
int foundIndex = binarySearch(output, unsorted[i], 0, i); // searches the right index using binary search
|
||||
for(int j = i; j > foundIndex; --j) { // shift each element after the found index one to the right
|
||||
output[j] = output[j - 1];
|
||||
}
|
||||
output[foundIndex] = unsorted[i];
|
||||
output[foundIndex] = unsorted[i]; // insert the element
|
||||
}
|
||||
return output;
|
||||
}
|
||||
private static int binarySearch(int[] array, int search, int minIndex, int maxIndex) {
|
||||
for(int j = maxIndex - 1; minIndex != maxIndex; j = minIndex + (maxIndex - minIndex) / 2) {
|
||||
if(search >= array[j]) {
|
||||
for(int j = maxIndex - 1; minIndex != maxIndex; j = minIndex + (maxIndex - minIndex) / 2 /* set j to middle between min and max Index */) {
|
||||
if(search >= array[j]) {// check if the element is larger and set min or max Index accordingly
|
||||
minIndex = j + 1;
|
||||
}
|
||||
else {
|
||||
@ -28,6 +28,7 @@ public class timsort {
|
||||
return minIndex;
|
||||
}
|
||||
public static int[] timsort(int[] unsorted) {
|
||||
// calculate minrun
|
||||
int r = 0;
|
||||
// r becomes 1 any 1 bits are shifted off
|
||||
int n = unsorted.length;
|
||||
@ -36,12 +37,14 @@ public class timsort {
|
||||
n >>= 1;
|
||||
}
|
||||
int minRun = n + r;
|
||||
|
||||
// split array into runs
|
||||
ArrayList<int[]> runs = new ArrayList<int[]>();
|
||||
for(int i = 0; i < unsorted.length - 1;) {
|
||||
int j = i;
|
||||
boolean ascending = true;
|
||||
boolean descending = true;
|
||||
boolean ascendingCache = false;
|
||||
boolean ascendingCache = false; // cache variables are needed to know if it is ascending or descending, both ascending and descending are false after the loop
|
||||
boolean descendingCache = false;
|
||||
for(; i < unsorted.length - 1 && (ascending || descending); ++i) {
|
||||
ascendingCache = ascending;
|
||||
@ -49,11 +52,11 @@ public class timsort {
|
||||
ascending = ascending && unsorted[i] <= unsorted[i + 1];
|
||||
descending = descending && unsorted[i] >= unsorted[i + 1];
|
||||
}
|
||||
if(i - j < minRun) i = j + minRun;
|
||||
boolean minRunNotMet = i >= unsorted.length - 1;
|
||||
if(minRunNotMet) i = unsorted.length;
|
||||
int[] temp1 = Arrays.copyOfRange(unsorted, j, i);
|
||||
if(!ascendingCache && descendingCache && !minRunNotMet) {
|
||||
boolean minRunNotMet = i - j < minRun;
|
||||
if(minRunNotMet) i = j + minRun; // if minrun is not met enlarge the array range
|
||||
if(i > unsorted.length) i = unsorted.length; // if the Index is out of Bounds set to the maxium.
|
||||
int[] temp1 = Arrays.copyOfRange(unsorted, j, i); // the index same as the length is not out of Bounds because copyOfRange is excluding the last index
|
||||
if(!ascendingCache && descendingCache && !minRunNotMet) { // if the array is descending and not ascending (if it is both all values are equal) and minrun is met (if it is not met the run is not ascending nor descending because of the enlargment of the run
|
||||
// reverses the array
|
||||
int l, temp;
|
||||
for(l = 0; l < temp1.length / 2; l++) {
|
||||
@ -64,43 +67,45 @@ public class timsort {
|
||||
}
|
||||
runs.add(temp1);
|
||||
}
|
||||
|
||||
int[][] notMerged = new int[runs.size()][];
|
||||
for(int i = 0; i < runs.size(); ++i) {
|
||||
for(int i = 0; i < runs.size(); ++i) { // sort each runs with insertionsort
|
||||
notMerged[i] = insertionsort(runs.get(i));
|
||||
}
|
||||
return merge(notMerged)[0];
|
||||
}
|
||||
private static int[][] merge(int[][] notMerged) {
|
||||
int notEvenLen = notMerged.length % 2;
|
||||
int[][] merged = new int[notMerged.length / 2 + notEvenLen][];
|
||||
for(int i = 0; i < notMerged.length - 1; i += 2) {
|
||||
int[] temp = new int[notMerged[i].length + notMerged[i + 1].length];
|
||||
int[][] merged = new int[notMerged.length / 2 + notEvenLen][]; // the merged array is half as the unmerged. if the length of notMerged is not even we have to add one because the one remaining arary will just be copied
|
||||
for(int i = 0; i < notMerged.length - 1; /* -1 becasue index of i + 1 is used later */ i += 2) {
|
||||
int[] temp = new int[notMerged[i].length + notMerged[i + 1].length]; // length of the merged is the sum of the 2 not merged arrays
|
||||
merged[i / 2] = temp;
|
||||
int[] j = new int[2];
|
||||
int w = 0;
|
||||
int[] j = new int[2]; // index variable: [0]: notMerged[i], [1]: notMerged[i + 1]
|
||||
int relativeIndexOfSmallerArray = 0;
|
||||
int l = 0;
|
||||
for(int gallopingCounter = 0; j[w] < notMerged[i + w].length; ++l) {
|
||||
if(gallopingCounter == 7) {
|
||||
int b = w != 0 ? 0 : 1;
|
||||
int found = binarySearch(notMerged[i + w], notMerged[i + b][j[b]], j[w], notMerged[i + w].length - 1);
|
||||
for(; j[w] < found; ++j[w], ++l) {
|
||||
temp[l] = notMerged[i + w][j[w]];
|
||||
for(int gallopingCounter = 0; j[relativeIndexOfSmallerArray] < notMerged[i + relativeIndexOfSmallerArray].length; ++l) {
|
||||
if(gallopingCounter == 7) { // do galloping if 7 elements in a row came from one array
|
||||
int relativeIndexOfLargerArray = relativeIndexOfSmallerArray != 0 ? 0 : 1;
|
||||
int found = binarySearch(notMerged[i + relativeIndexOfSmallerArray], notMerged[i + relativeIndexOfLargerArray][j[relativeIndexOfLargerArray]], j[relativeIndexOfSmallerArray], notMerged[i + relativeIndexOfSmallerArray].length - 1); // use binray search to out how many elements can be copied from the same array
|
||||
for(; j[relativeIndexOfSmallerArray] < found; ++j[relativeIndexOfSmallerArray], ++l) { // copy elements
|
||||
temp[l] = notMerged[i + relativeIndexOfSmallerArray][j[relativeIndexOfSmallerArray]];
|
||||
}
|
||||
}
|
||||
int lastW = w;
|
||||
w = notMerged[i][j[0]] > notMerged[i + 1][j[1]] ? 1 : 0;
|
||||
temp[l] = notMerged[i + w][j[w]];
|
||||
++j[w];
|
||||
if(w == lastW) ++gallopingCounter;
|
||||
int lastRelativeIndexOfSmallerArray = relativeIndexOfSmallerArray;
|
||||
relativeIndexOfSmallerArray = notMerged[i][j[0]] > notMerged[i + 1][j[1]] ? 1 : 0;
|
||||
temp[l] = notMerged[i + relativeIndexOfSmallerArray][j[relativeIndexOfSmallerArray]]; // copy the element to the output array
|
||||
++j[relativeIndexOfSmallerArray];
|
||||
if(relativeIndexOfSmallerArray == lastRelativeIndexOfSmallerArray ) ++gallopingCounter;
|
||||
else gallopingCounter = 0;
|
||||
}
|
||||
int b = w != 0 ? 0 : 1;
|
||||
for(int k = j[b]; l < temp.length; ++k, ++l) {
|
||||
temp[l] = notMerged[i + b][k];
|
||||
// after one of the not merged arrays is empty the remaining elements from the other arrays have to be copied
|
||||
int relativeIndexOfLargerArray = relativeIndexOfSmallerArray != 0 ? 0 : 1;
|
||||
for(int k = j[relativeIndexOfLargerArray]; l < temp.length; ++k, ++l) {
|
||||
temp[l] = notMerged[i + relativeIndexOfLargerArray][k];
|
||||
}
|
||||
}
|
||||
if(notEvenLen == 1) merged[merged.length - 1] = notMerged[notMerged.length - 1];
|
||||
if(merged.length == 1) return merged;
|
||||
return merge(merged);
|
||||
if(notEvenLen == 1) merged[merged.length - 1] = notMerged[notMerged.length - 1]; // copy the last array if input array length is uneven so array could not be merged
|
||||
if(merged.length == 1) return merged; // sorting is finnished
|
||||
return merge(merged); // do merging again
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user