JavaAlgorithms/Sorts/TimSort.java
Hemanth Kotagiri 66adafbff8
Tim sort Algorithm | #2003 (#2110)
* Add Tim Sort implementation in Java

* Add comments and complete implementation of TimSort Algorithm

* Add better docs

* Add @brief's and test method

* Fix errors

* add Test method

* Update Sorts/TimSort.java

Co-authored-by: Ayaan Khan <ayaankhan98@gmail.com>

* Update Sorts/TimSort.java

Co-authored-by: Ayaan Khan <ayaankhan98@gmail.com>

* Update Sorts/TimSort.java

Co-authored-by: Ayaan Khan <ayaankhan98@gmail.com>

* Update Sorts/TimSort.java

Co-authored-by: Ayaan Khan <ayaankhan98@gmail.com>

* Update Sorts/TimSort.java

Co-authored-by: Ayaan Khan <ayaankhan98@gmail.com>

* Update Sorts/TimSort.java

Co-authored-by: Ayaan Khan <ayaankhan98@gmail.com>

* Update Sorts/TimSort.java

Co-authored-by: Ayaan Khan <ayaankhan98@gmail.com>

* Update Sorts/TimSort.java

Co-authored-by: Ayaan Khan <ayaankhan98@gmail.com>

* Add tests

* Update Sorts/TimSort.java

Co-authored-by: Ayaan Khan <ayaankhan98@gmail.com>

* Update Sorts/TimSort.java

* Update Sorts/TimSort.java

Co-authored-by: Ayaan Khan <ayaankhan98@gmail.com>

* Update Sorts/TimSort.java

Co-authored-by: Ayaan Khan <ayaankhan98@gmail.com>

* Update Sorts/TimSort.java

Co-authored-by: Ayaan Khan <ayaankhan98@gmail.com>

Co-authored-by: Ayaan Khan <ayaankhan98@gmail.com>
2021-04-23 22:57:41 +05:30

214 lines
6.1 KiB
Java

package Sorts;
import java.lang.Math;
import java.util.Random;
/**
* @author [Hemanth Kotagiri](https://github.com/hemanth-kotagiri)
* @see [Tim Sort](https://en.wikipedia.org/wiki/Tim_sort)
*/
class TimSort {
int array[];
int array_length;
int RUN = 32;
/**
* @brief A constructor which takes in the array specified by the user.
* @param array : Array given by the user.
*/
public TimSort(int[] array) {
this.array = array;
this.array_length = array.length;
}
/**
* @brief A constructor which takes in an array length and randomly
* initializes an array.
* @param array_length length given by the user.
*/
public TimSort(int array_length) {
Random rand = new Random();
this.array_length = array_length;
this.array = new int[this.array_length];
for (int i = 0; i < this.array_length; i++) {
int random_number = rand.nextInt(1000);
this.array[i] = random_number;
}
}
/**
* @brief A method to change the size of the run.
* @param run : Value specified by the user to change the run.
*/
public void change_run(int run) {
this.RUN = run;
}
/**
* @brief A default constructor when no parameters are given.
* Initializes the array length to be 100.
* Generates a random number array of size 100.
*/
public TimSort() {
this.array_length = 100;
this.array = new int[this.array_length];
Random rand = new Random();
for (int i = 0; i < this.array_length; i++) {
int random_number = rand.nextInt(1000);
this.array[i] = random_number;
}
}
/**
* @brief Performs Insertion Sort Algorithm on given array with bounded
* indices.
* @param array: The array on which the algorithm is to be performed.
* @param start_idx: The starting index from which the algorithm is to be
* performed.
* @param end_idx: The ending index at which the algorithm needs to stop
* sorting.
*/
public void insertion_sort(int[] array, int start_idx, int end_idx) {
for (int i = 0; i < array.length; i++) {
int current_element = array[i];
int j = i - 1;
while (j >= 0 && array[j] > current_element) {
array[j + 1] = array[j];
j--;
}
array[j + 1] = current_element;
}
}
/**
* @brief A method to merge two runs(chunks of array).
* @param array: The origin array which is to be sorted.
* @param start: Starting index of the first run(chunk).
* @param mid: The ending index of the first run(chunk).
* @param end: Ending index of the second run(chunk).
*/
public void merge_runs(int array[], int start, int mid, int end) {
int first_array_size = mid - start + 1, second_array_size = end - mid;
int array1[] = new int[first_array_size], array2[] = new int[second_array_size];
int i = 0, j = 0, k = 0;
// Building the two sub arrays from the array to merge later
for (i = 0; i < first_array_size; i++)
array1[i] = array[start + i];
for (i = 0; i < second_array_size; i++)
array2[i] = array[mid + 1 + i];
i = 0;
j = 0;
k = start;
while (i < first_array_size && j < second_array_size) {
if (array1[i] <= array2[j]) {
array[k] = array1[i];
i++;
} else {
array[k] = array2[j];
j++;
}
k++;
}
while (i < first_array_size) {
array[k] = array1[i];
k++;
i++;
}
while (j < second_array_size) {
array[k] = array2[j];
k++;
j++;
}
}
/**
* @brief Tim Sort Algorithm method.
*/
public void algorithm() {
// Before Sorting
System.out.println("Before sorting the array: ");
this.showArrayElements();
System.out.println();
// Applying insertion sort on RUNS.
for (int i = 0; i < this.array_length; i += this.RUN)
this.insertion_sort(this.array, i, Math.min(i + this.RUN, (this.array_length - 1)));
for (int split = this.RUN; split < this.array_length; split = 2 * split) {
for (int start_idx = 0; start_idx < this.array_length; start_idx += 2 * split) {
int mid = start_idx + split - 1;
int end_idx = Math.min((start_idx + 2 * split - 1), (this.array_length - 1));
this.merge_runs(this.array, start_idx, mid, end_idx);
}
}
// After sorting
System.out.println("After sorting the array: ");
this.showArrayElements();
System.out.println();
}
/**
* @brief A method to show the elements inside the array.
*/
public void showArrayElements() {
for (int i = 0; i < this.array.length; i++) {
System.out.print(this.array[i] + " ");
}
System.out.println();
}
/**
* @brief A method to test the sorting algorithm
*/
static void test() {
int[] array = { 4, 1, 3, 17, 12, 11, 8 };
TimSort sorterObj1 = new TimSort();
TimSort sorterObj2 = new TimSort(50);
TimSort sorterObj3 = new TimSort(array);
sorterObj1.algorithm();
sorterObj2.algorithm();
sorterObj3.algorithm();
// Testing the first array
for(int i = 0; i < sorterObj1.array_length - 1; i++) {
assert((sorterObj1.array[i] <= sorterObj1.array[i +1])) : "Array is not sorted";
}
// Testing the second array.
for(int i = 0; i < sorterObj2.array_length - 1; i++) {
assert((sorterObj2.array[i] <= sorterObj2.array[i + 1])) : "Array is not sorted";
}
// Testing the third array.
for(int i = 0; i < sorterObj3.array_length - 1; i++) {
assert((sorterObj3.array[i] <= sorterObj3.array[i + 1])) : "Array is not sorted";
}
}
public static void main(String[] args) {
test();
}
}