comments
This commit is contained in:
@ -6,9 +6,12 @@ import de.redstoneunion.git.MrGeorgen.timsort.timsort;
|
|||||||
|
|
||||||
public class test {
|
public class test {
|
||||||
public static void main(String[] args) {
|
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};
|
long startTime = System.nanoTime();
|
||||||
int[] output = timsort.insertionsort(array);
|
int[] test = timsort.timsort(new int[]{20, 1, 573, 34, 281, 201, 0});
|
||||||
System.out.println("Insertionsort test: " + Arrays.toString(output));
|
long endTime = System.nanoTime();
|
||||||
System.out.println("End result: " + Arrays.toString(timsort.timsort(array)));
|
|
||||||
|
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;
|
import java.util.Arrays;
|
||||||
|
|
||||||
public class timsort {
|
public class timsort {
|
||||||
public static int[] insertionsort(int[] unsorted) {
|
private static int[] insertionsort(int[] unsorted) {
|
||||||
int[] output = new int[unsorted.length];
|
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) {
|
for(int i = 1; i < unsorted.length; ++i) {
|
||||||
int foundIndex = binarySearch(output, unsorted[i], 0, i);
|
int foundIndex = binarySearch(output, unsorted[i], 0, i); // searches the right index using binary search
|
||||||
for(int j = i; j > foundIndex; --j) {
|
for(int j = i; j > foundIndex; --j) { // shift each element after the found index one to the right
|
||||||
output[j] = output[j - 1];
|
output[j] = output[j - 1];
|
||||||
}
|
}
|
||||||
output[foundIndex] = unsorted[i];
|
output[foundIndex] = unsorted[i]; // insert the element
|
||||||
}
|
}
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
private static int binarySearch(int[] array, int search, int minIndex, int maxIndex) {
|
private static int binarySearch(int[] array, int search, int minIndex, int maxIndex) {
|
||||||
for(int j = maxIndex - 1; minIndex != maxIndex; j = minIndex + (maxIndex - minIndex) / 2) {
|
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]) {
|
if(search >= array[j]) {// check if the element is larger and set min or max Index accordingly
|
||||||
minIndex = j + 1;
|
minIndex = j + 1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -28,6 +28,7 @@ public class timsort {
|
|||||||
return minIndex;
|
return minIndex;
|
||||||
}
|
}
|
||||||
public static int[] timsort(int[] unsorted) {
|
public static int[] timsort(int[] unsorted) {
|
||||||
|
// calculate minrun
|
||||||
int r = 0;
|
int r = 0;
|
||||||
// r becomes 1 any 1 bits are shifted off
|
// r becomes 1 any 1 bits are shifted off
|
||||||
int n = unsorted.length;
|
int n = unsorted.length;
|
||||||
@ -36,12 +37,14 @@ public class timsort {
|
|||||||
n >>= 1;
|
n >>= 1;
|
||||||
}
|
}
|
||||||
int minRun = n + r;
|
int minRun = n + r;
|
||||||
|
|
||||||
|
// split array into runs
|
||||||
ArrayList<int[]> runs = new ArrayList<int[]>();
|
ArrayList<int[]> runs = new ArrayList<int[]>();
|
||||||
for(int i = 0; i < unsorted.length - 1;) {
|
for(int i = 0; i < unsorted.length - 1;) {
|
||||||
int j = i;
|
int j = i;
|
||||||
boolean ascending = true;
|
boolean ascending = true;
|
||||||
boolean descending = 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;
|
boolean descendingCache = false;
|
||||||
for(; i < unsorted.length - 1 && (ascending || descending); ++i) {
|
for(; i < unsorted.length - 1 && (ascending || descending); ++i) {
|
||||||
ascendingCache = ascending;
|
ascendingCache = ascending;
|
||||||
@ -49,11 +52,11 @@ public class timsort {
|
|||||||
ascending = ascending && unsorted[i] <= unsorted[i + 1];
|
ascending = ascending && unsorted[i] <= unsorted[i + 1];
|
||||||
descending = descending && unsorted[i] >= unsorted[i + 1];
|
descending = descending && unsorted[i] >= unsorted[i + 1];
|
||||||
}
|
}
|
||||||
if(i - j < minRun) i = j + minRun;
|
boolean minRunNotMet = i - j < minRun;
|
||||||
boolean minRunNotMet = i >= unsorted.length - 1;
|
if(minRunNotMet) i = j + minRun; // if minrun is not met enlarge the array range
|
||||||
if(minRunNotMet) i = unsorted.length;
|
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);
|
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(!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
|
// reverses the array
|
||||||
int l, temp;
|
int l, temp;
|
||||||
for(l = 0; l < temp1.length / 2; l++) {
|
for(l = 0; l < temp1.length / 2; l++) {
|
||||||
@ -64,43 +67,45 @@ public class timsort {
|
|||||||
}
|
}
|
||||||
runs.add(temp1);
|
runs.add(temp1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int[][] notMerged = new int[runs.size()][];
|
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));
|
notMerged[i] = insertionsort(runs.get(i));
|
||||||
}
|
}
|
||||||
return merge(notMerged)[0];
|
return merge(notMerged)[0];
|
||||||
}
|
}
|
||||||
private static int[][] merge(int[][] notMerged) {
|
private static int[][] merge(int[][] notMerged) {
|
||||||
int notEvenLen = notMerged.length % 2;
|
int notEvenLen = notMerged.length % 2;
|
||||||
int[][] merged = new int[notMerged.length / 2 + notEvenLen][];
|
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; i += 2) {
|
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];
|
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;
|
merged[i / 2] = temp;
|
||||||
int[] j = new int[2];
|
int[] j = new int[2]; // index variable: [0]: notMerged[i], [1]: notMerged[i + 1]
|
||||||
int w = 0;
|
int relativeIndexOfSmallerArray = 0;
|
||||||
int l = 0;
|
int l = 0;
|
||||||
for(int gallopingCounter = 0; j[w] < notMerged[i + w].length; ++l) {
|
for(int gallopingCounter = 0; j[relativeIndexOfSmallerArray] < notMerged[i + relativeIndexOfSmallerArray].length; ++l) {
|
||||||
if(gallopingCounter == 7) {
|
if(gallopingCounter == 7) { // do galloping if 7 elements in a row came from one array
|
||||||
int b = w != 0 ? 0 : 1;
|
int relativeIndexOfLargerArray = relativeIndexOfSmallerArray != 0 ? 0 : 1;
|
||||||
int found = binarySearch(notMerged[i + w], notMerged[i + b][j[b]], j[w], notMerged[i + w].length - 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[w] < found; ++j[w], ++l) {
|
for(; j[relativeIndexOfSmallerArray] < found; ++j[relativeIndexOfSmallerArray], ++l) { // copy elements
|
||||||
temp[l] = notMerged[i + w][j[w]];
|
temp[l] = notMerged[i + relativeIndexOfSmallerArray][j[relativeIndexOfSmallerArray]];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int lastW = w;
|
int lastRelativeIndexOfSmallerArray = relativeIndexOfSmallerArray;
|
||||||
w = notMerged[i][j[0]] > notMerged[i + 1][j[1]] ? 1 : 0;
|
relativeIndexOfSmallerArray = notMerged[i][j[0]] > notMerged[i + 1][j[1]] ? 1 : 0;
|
||||||
temp[l] = notMerged[i + w][j[w]];
|
temp[l] = notMerged[i + relativeIndexOfSmallerArray][j[relativeIndexOfSmallerArray]]; // copy the element to the output array
|
||||||
++j[w];
|
++j[relativeIndexOfSmallerArray];
|
||||||
if(w == lastW) ++gallopingCounter;
|
if(relativeIndexOfSmallerArray == lastRelativeIndexOfSmallerArray ) ++gallopingCounter;
|
||||||
else gallopingCounter = 0;
|
else gallopingCounter = 0;
|
||||||
}
|
}
|
||||||
int b = w != 0 ? 0 : 1;
|
// after one of the not merged arrays is empty the remaining elements from the other arrays have to be copied
|
||||||
for(int k = j[b]; l < temp.length; ++k, ++l) {
|
int relativeIndexOfLargerArray = relativeIndexOfSmallerArray != 0 ? 0 : 1;
|
||||||
temp[l] = notMerged[i + b][k];
|
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(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;
|
if(merged.length == 1) return merged; // sorting is finnished
|
||||||
return merge(merged);
|
return merge(merged); // do merging again
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user