Home - Larisa-Mishura/aLevel GitHub Wiki

Tim Sort Algorithm

Tim-sort is a sorting algorithm derived from insertion sort and merge sort. It was designed to perform optimally on different kind of real-world data. Tim sort is an adaptive sorting algorithm that needs O(n log n) comparisons to sort an array of n elements. It was designed and implemented by Tim Peters in 2002 in a python programming language. It has been python's standard sorting algorithm since version 2.3. It is the fastest sorting algorithm. The basic approach used in the Tim sort algorithm is - first sort small chunks by using the insertion sort and then merge all the big chunks using the merge function of the merge sort. Now, let's see the algorithm of Tim sort.

Algorithm

Step 1 - Divide the array into the number of blocks known as run.
Step 2 - Consider the size of run, either 32 or 64.
Step 3 - Sort the individual elements of every run one by one using insertion sort.
Step 4 - Merge the sorted runs one by one using the merge function of merge sort.
Step 5 - Double the size of merged sub-arrays after every iteration.

Working of Tim sort Algorithm

In Tim sort, first the array is divided into small chunks that are known as RUN. After dividing, each individual RUN is taken, and sorted using the insertion sort technique. After that, all sorted RUNs are merged using the merge() function of the merge sort algorithm. In Tim sort, the advantage of using the insertion sort is that insertion sort works efficiently for the array with small size.

Example of Tim sort Algorithm

Let's see the example of Tim sort algorithm. To understand the working of Tim sort algorithm, let's take an unsorted array. It will be easier to understand the Tim sort via an example.

Suppose the array elements are -

image

For the simple illustration, let's consider the size of RUN is 4.

Now, divide the given array into two sub-arrays that are -

image

The first sub-array is

image

image

First iteration

a[1] = 10

image

Second iteration

a[2] = 20

image

Third iteration

a[3] = 42

image

The second sub-array is

image

image

First iteration

a[1] = 25

image

Second iteration

a[2] = 1

image

Third iteration

a[3] = 19

image

Now, merge both sorted subarrays to get the final array as -

image

Now, the array is completely sorted.

Tim sort complexity

1. Time Complexity

image

  • Best Case Complexity - It occurs when there is no sorting required, i.e. the array is already sorted. The best-case time complexity of Tim sort is O(n).
  • Average Case Complexity - It occurs when the array elements are in jumbled order that is not properly ascending and not properly descending. The average case time complexity of Tim sort is O(n log n).
  • Worst Case Complexity - It occurs when the array elements are required to be sorted in reverse order. That means suppose you have to sort the array elements in ascending order, but its elements are in descending order. The worst-case time complexity of Tim sort is O(n log n).

2. Space Complexity

image

The space complexity of Tim sort is O(n).

Implementation of Tim sort

import java.util.Arrays;

public class TimSort {
final static int RUN = 32;
final static int[] numbers = {38, 10, 29, 25, 23, 6, 2, 30, 15, 56, 7};

public static void main(String[] args) {
    System.out.print("Before sorting - ");
    System.out.println(Arrays.toString(numbers));
    timSort(numbers);
    System.out.print("After sorting - ");
    System.out.println(Arrays.toString(numbers));
}

/* Method sorts array with insertion sort from starting index to ending index which is of size atmost RUN */
public static void insertionSort(int[] arr, int begin, int finish) {
    for (int i = begin + 1; i <= finish; i++) {
        int temp = arr[i];
        int j = i - 1;

        while (j >= begin && temp <= arr[j]) {
            arr[j + 1] = arr[j];
            j = j - 1;
        }
        arr[j + 1] = temp;
    }
}

/* Method to merge the sorted runs */
public static void merge(int[] arr, int start, int mid, int finish) {
    int[] leftArray = new int[mid - start + 1]; //n1
    int[] rightArray = new int[finish - mid];  //n2
    System.arraycopy(arr, start, leftArray, 0, mid - start + 1);
    System.arraycopy(arr, mid + 1, rightArray, 0, finish - mid);

    int i = 0;
    int j = 0;
    int k = start;
    while (i < leftArray.length && j < rightArray.length) {
        if (leftArray[i] <= rightArray[j]) {
            arr[k++] = leftArray[i++];
        } else {
            arr[k++] = rightArray[j++];
        }
    }
    while (i < leftArray.length) {
        arr[k++] = leftArray[i++];
    }
    while (j < rightArray.length) {
        arr[k++] = rightArray[j++];
    }
}

    /* method to implement tim sort */
public static void timSort(int[] arr) {
    int n = arr.length;
    for (int i = 0; i < n; i += RUN) {
        insertionSort(arr, i, min((i + RUN - 1), (n - 1)));
    }

    for (int size = RUN; size < n; size = 2 * size) {
        for (int beg = 0; beg < n; beg += 2 * size) {
            /* find ending point of left subarray. The starting point of right sub array is mid + 1 */
            int mid = beg + size - 1;
            int end = min((beg + 2 * size - 1), (n - 1));

            /* Merge subarray a[beg...mid] and a[mid +1...end] */
            if (mid < end)
                merge(arr, beg, mid, end);
        }
    }
}

public static int min(int a, int b) {
    if (a < b) {
        return a;
    } else {
        return b;
    }
  }
}