diff --git a/Sorts/TimSort.java b/Sorts/TimSort.java index 37efa5943..8a6c5e11b 100644 --- a/Sorts/TimSort.java +++ b/Sorts/TimSort.java @@ -1,213 +1,188 @@ 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; + 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. - */ + /** + * @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; + } - 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++; } - /** - * @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; - } + while (i < first_array_size) { + array[k] = array1[i]; + k++; + i++; } - /** - * @brief A method to change the size of the run. - * @param run : Value specified by the user to change the run. - */ + while (j < second_array_size) { + array[k] = array2[j]; + k++; + j++; + } + } - public void change_run(int run) { - this.RUN = run; + /** @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"; } - /** - * @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; - } + // 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"; } - /** - * @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; - } + // 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"; } + } - /** - * @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(); - } + public static void main(String[] args) { + test(); + } }