R Program to Implement Tim Sort

R Program to Implement Tim Sort

Tim Sort is a modern and powerful sorting algorithm that combines the best ideas from Merge Sort and Insertion Sort. It was designed to work very well on real-world data, especially data that is already partially sorted. Instead of blindly sorting everything from scratch, Tim Sort looks for small sorted pieces in the data and uses them to make sorting faster and smarter. This makes it a great algorithm to learn once you are comfortable with basic sorting ideas in R.

Tim Sort is widely used in real programming languages and systems because it is stable, efficient, and reliable. For example, it is the default sorting algorithm in languages like Python and Java. Learning how Tim Sort works in R helps beginners understand how classic algorithms evolve over time to solve practical problems better. It also teaches how combining simple techniques can lead to powerful results.

Program 1: Basic Tim Sort using insertion sort and merge logic

This first program shows a simple Tim Sort implementation using insertion sort for small runs and merge logic to combine them. It focuses on clarity so beginners can follow along easily.

insertion_sort <- function(arr, left, right) {

  for (i in (left + 1):right) {

    key <- arr[i]
    j <- i - 1

    while (j >= left && arr[j] > key) {
      arr[j + 1] <- arr[j]
      j <- j - 1
    }

    arr[j + 1] <- key

  }

  return(arr)

}

merge <- function(arr, l, m, r) {

  left <- arr[l:m]
  right <- arr[(m + 1):r]
  i <- j <- 1
  k <- l

  while (i <= length(left) && j <= length(right)) {

    if (left[i] <= right[j]) {

      arr[k] <- left[i]
      i <- i + 1

    } else {

      arr[k] <- right[j]
      j <- j + 1

    }

    k <- k + 1

  }

  while (i <= length(left)) {

    arr[k] <- left[i]
    i <- i + 1
    k <- k + 1

  }

  while (j <= length(right)) {

    arr[k] <- right[j]
    j <- j + 1
    k <- k + 1

  }

  return(arr)

}

tim_sort <- function(arr) {

  n <- length(arr)
  run <- 32

  for (i in seq(1, n, by = run)) {
    arr <- insertion_sort(arr, i, min(i + run - 1, n))
  }

  size <- run

  while (size < n) {

    for (left in seq(1, n, by = 2 * size)) {

      mid <- left + size - 1
      right <- min(left + 2 * size - 1, n)

      if (mid < right) {
        arr <- merge(arr, left, mid, right)
      }

    }

    size <- size * 2

  }

  return(arr)

}

data <- c(5, 21, 7, 23, 19, 10, 3)
print(tim_sort(data))

This program works by first sorting small chunks using insertion sort, then merging those chunks together. Beginners can see how Tim Sort builds on familiar ideas instead of introducing completely new ones. It is useful because it mirrors how Tim Sort behaves in real systems.

Program 2: Tim Sort with smaller run size for learning

This version reduces the run size to make it easier to observe how the algorithm behaves on small inputs.

insertion_sort <- function(arr, left, right) {

  for (i in (left + 1):right) {

    key <- arr[i]
    j <- i - 1

    while (j >= left && arr[j] > key) {
      arr[j + 1] <- arr[j]
      j <- j - 1
    }

    arr[j + 1] <- key

  }

  return(arr)

}

merge <- function(arr, l, m, r) {

  left <- arr[l:m]
  right <- arr[(m + 1):r]
  i <- j <- 1
  k <- l

  while (i <= length(left) && j <= length(right)) {

    if (left[i] <= right[j]) {

      arr[k] <- left[i]
      i <- i + 1

    } else {

      arr[k] <- right[j]
      j <- j + 1

    }

    k <- k + 1

  }

  while (i <= length(left)) {

    arr[k] <- left[i]
    i <- i + 1
    k <- k + 1

  }

  while (j <= length(right)) {

    arr[k] <- right[j]
    j <- j + 1
    k <- k + 1

  }

  return(arr)

}

tim_sort_small_run <- function(arr) {

  n <- length(arr)
  run <- 4

  for (i in seq(1, n, by = run)) {
    arr <- insertion_sort(arr, i, min(i + run - 1, n))
  }

  size <- run

  while (size < n) {

    for (left in seq(1, n, by = 2 * size)) {

      mid <- left + size - 1
      right <- min(left + 2 * size - 1, n)

      if (mid < right) {
        arr <- merge(arr, left, mid, right)
      }

    }

    size <- size * 2

  }

  return(arr)

}

data <- c(12, 11, 13, 5, 6, 7)
print(tim_sort_small_run(data))

By using smaller runs, beginners can step through the algorithm more easily. This makes Tim Sort less intimidating and helps learners understand how sorting happens in stages.

Program 3: Tim Sort written in a very clear and traditional style

This program focuses on readability and traditional step-by-step logic.

insertion_sort <- function(arr, left, right) {

  for (i in (left + 1):right) {

    key <- arr[i]
    j <- i - 1

    while (j >= left && arr[j] > key) {
      arr[j + 1] <- arr[j]
      j <- j - 1
    }

    arr[j + 1] <- key

  }

  return(arr)

}

merge <- function(arr, l, m, r) {

  left <- arr[l:m]
  right <- arr[(m + 1):r]
  i <- j <- 1
  k <- l

  while (i <= length(left) && j <= length(right)) {

    if (left[i] <= right[j]) {

      arr[k] <- left[i]
      i <- i + 1

    } else {

      arr[k] <- right[j]
      j <- j + 1

    }

    k <- k + 1

  }

  while (i <= length(left)) {

    arr[k] <- left[i]
    i <- i + 1
    k <- k + 1

  }

  while (j <= length(right)) {

    arr[k] <- right[j]
    j <- j + 1
    k <- k + 1

  }

  return(arr)

}

tim_sort_clear <- function(arr) {

  n <- length(arr)
  run <- 8

  for (start in seq(1, n, by = run)) {

    end <- min(start + run - 1, n)
    arr <- insertion_sort(arr, start, end)

  }

  size <- run

  while (size < n) {

    left <- 1

    while (left <= n) {

      mid <- left + size - 1
      right <- min(left + 2 * size - 1, n)

      if (mid < right) {
        arr <- merge(arr, left, mid, right)
      }

      left <- left + 2 * size

    }

    size <- size * 2

  }

  return(arr)

}

data <- c(20, 35, 15, 7, 55, 1, 22)
print(tim_sort_clear(data))

This version is helpful for beginners who want to trace each step carefully. It shows how order gradually emerges as runs are merged together.

Program 4: Tim Sort using helper functions only

This program separates responsibilities clearly, following a classic programming mindset.

insertion_sort <- function(arr, left, right) {

  for (i in (left + 1):right) {

    key <- arr[i]
    j <- i - 1

    while (j >= left && arr[j] > key) {
      arr[j + 1] <- arr[j]
      j <- j - 1
    }

    arr[j + 1] <- key

  }

  return(arr)

}

merge <- function(arr, l, m, r) {

  left <- arr[l:m]
  right <- arr[(m + 1):r]
  i <- j <- 1
  k <- l

  while (i <= length(left) && j <= length(right)) {

    if (left[i] <= right[j]) {

      arr[k] <- left[i]
      i <- i + 1

    } else {

      arr[k] <- right[j]
      j <- j + 1

    }

    k <- k + 1

  }

  while (i <= length(left)) {

    arr[k] <- left[i]
    i <- i + 1
    k <- k + 1

  }

  while (j <= length(right)) {

    arr[k] <- right[j]
    j <- j + 1
    k <- k + 1

  }

  return(arr)

}

tim_sort_helpers <- function(arr) {

  n <- length(arr)
  run <- 16

  for (i in seq(1, n, by = run)) {
    arr <- insertion_sort(arr, i, min(i + run - 1, n))
  }

  size <- run

  while (size < n) {

    for (i in seq(1, n, by = 2 * size)) {

      mid <- i + size - 1
      end <- min(i + 2 * size - 1, n)

      if (mid < end) {
        arr <- merge(arr, i, mid, end)
      }

    }

    size <- size * 2

  }

  return(arr)

}

data <- c(9, 8, 3, 7, 5, 6, 4)
print(tim_sort_helpers(data))

Breaking logic into helper functions makes the code easier to maintain. Beginners learn a good habit that applies to all programming, not just sorting.

Program 5: Tim Sort optimized for nearly sorted data

This example highlights why Tim Sort performs so well when data is already partially sorted.

insertion_sort <- function(arr, left, right) {

  for (i in (left + 1):right) {

    key <- arr[i]
    j <- i - 1

    while (j >= left && arr[j] > key) {
      arr[j + 1] <- arr[j]
      j <- j - 1
    }

    arr[j + 1] <- key

  }

  return(arr)

}

merge <- function(arr, l, m, r) {

  left <- arr[l:m]
  right <- arr[(m + 1):r]
  i <- j <- 1
  k <- l

  while (i <= length(left) && j <= length(right)) {

    if (left[i] <= right[j]) {

      arr[k] <- left[i]
      i <- i + 1

    } else {

      arr[k] <- right[j]
      j <- j + 1

    }

    k <- k + 1

  }

  while (i <= length(left)) {

    arr[k] <- left[i]
    i <- i + 1
    k <- k + 1

  }

  while (j <= length(right)) {

    arr[k] <- right[j]
    j <- j + 1
    k <- k + 1

  }

  return(arr)

}

tim_sort_near_sorted <- function(arr) {

  n <- length(arr)
  run <- 32

  for (i in seq(1, n, by = run)) {
    arr <- insertion_sort(arr, i, min(i + run - 1, n))
  }

  size <- run

  while (size < n) {

    for (i in seq(1, n, by = 2 * size)) {

      mid <- i + size - 1
      right <- min(i + 2 * size - 1, n)

      if (mid < right) {
        arr <- merge(arr, i, mid, right)
      }

    }

    size <- size * 2

  }

  return(arr)

}

data <- c(1, 2, 3, 7, 5, 6, 8)
print(tim_sort_near_sorted(data))

Tim Sort quickly finishes because insertion sort handles the small disorder efficiently. Beginners can see why this algorithm is preferred in real-world software.

Program 6: Tim Sort using while loops for practice

This version uses while loops to help learners practice loop control.

insertion_sort <- function(arr, left, right) {

  for (i in (left + 1):right) {

    key <- arr[i]
    j <- i - 1

    while (j >= left && arr[j] > key) {
      arr[j + 1] <- arr[j]
      j <- j - 1
    }

    arr[j + 1] <- key

  }

  return(arr)

}

merge <- function(arr, l, m, r) {

  left <- arr[l:m]
  right <- arr[(m + 1):r]
  i <- j <- 1
  k <- l

  while (i <= length(left) && j <= length(right)) {

    if (left[i] <= right[j]) {

      arr[k] <- left[i]
      i <- i + 1

    } else {

      arr[k] <- right[j]
      j <- j + 1

    }

    k <- k + 1

  }

  while (i <= length(left)) {

    arr[k] <- left[i]
    i <- i + 1
    k <- k + 1

  }

  while (j <= length(right)) {

    arr[k] <- right[j]
    j <- j + 1
    k <- k + 1

  }

  return(arr)

}

tim_sort_while <- function(arr) {

  n <- length(arr)
  run <- 8
  i <- 1

  while (i <= n) {
    arr <- insertion_sort(arr, i, min(i + run - 1, n))
    i <- i + run
  }

  size <- run

  while (size < n) {

    left <- 1

    while (left <= n) {

      mid <- left + size - 1
      right <- min(left + 2 * size - 1, n)

      if (mid < right) {
        arr <- merge(arr, left, mid, right)
      }

      left <- left + 2 * size

    }

    size <- size * 2

  }

  return(arr)

}

data <- c(14, 3, 27, 1, 19, 8)
print(tim_sort_while(data))

This helps beginners become comfortable with different loop styles while keeping the algorithm logic unchanged.

Program 7: Tim Sort with input validation

This program adds safety checks to ensure clean input.

insertion_sort <- function(arr, left, right) {

  for (i in (left + 1):right) {

    key <- arr[i]
    j <- i - 1

    while (j >= left && arr[j] > key) {
      arr[j + 1] <- arr[j]
      j <- j - 1
    }

    arr[j + 1] <- key

  }

  return(arr)

}

merge <- function(arr, l, m, r) {

  left <- arr[l:m]
  right <- arr[(m + 1):r]
  i <- j <- 1
  k <- l

  while (i <= length(left) && j <= length(right)) {

    if (left[i] <= right[j]) {

      arr[k] <- left[i]
      i <- i + 1

    } else {

      arr[k] <- right[j]
      j <- j + 1

    }

    k <- k + 1

  }

  while (i <= length(left)) {

    arr[k] <- left[i]
    i <- i + 1
    k <- k + 1

  }

  while (j <= length(right)) {

    arr[k] <- right[j]
    j <- j + 1
    k <- k + 1

  }

  return(arr)

}

tim_sort <- function(arr) {

  n <- length(arr)
  run <- 32

  for (i in seq(1, n, by = run)) {
    arr <- insertion_sort(arr, i, min(i + run - 1, n))
  }

  size <- run

  while (size < n) {

    for (left in seq(1, n, by = 2 * size)) {

      mid <- left + size - 1
      right <- min(left + 2 * size - 1, n)

      if (mid < right) {
        arr <- merge(arr, left, mid, right)
      }

    }

    size <- size * 2

  }

  return(arr)

}

tim_sort_safe <- function(arr) {

  if (!is.numeric(arr)) {
    stop("Input must be numeric")
  }

  tim_sort(arr)

}

data <- c(16, 4, 10, 2, 8)
print(tim_sort_safe(data))

This teaches beginners that writing reliable programs is just as important as writing correct ones.

Program 8: Tim Sort for larger datasets

This version demonstrates Tim Sort on a slightly larger predefined dataset.

insertion_sort <- function(arr, left, right) {

  for (i in (left + 1):right) {

    key <- arr[i]
    j <- i - 1

    while (j >= left && arr[j] > key) {
      arr[j + 1] <- arr[j]
      j <- j - 1
    }

    arr[j + 1] <- key

  }

  return(arr)

}

merge <- function(arr, l, m, r) {

  left <- arr[l:m]
  right <- arr[(m + 1):r]
  i <- j <- 1
  k <- l

  while (i <= length(left) && j <= length(right)) {

    if (left[i] <= right[j]) {

      arr[k] <- left[i]
      i <- i + 1

    } else {

      arr[k] <- right[j]
      j <- j + 1

    }

    k <- k + 1

  }

  while (i <= length(left)) {

    arr[k] <- left[i]
    i <- i + 1
    k <- k + 1

  }

  while (j <= length(right)) {

    arr[k] <- right[j]
    j <- j + 1
    k <- k + 1

  }

  return(arr)

}

tim_sort <- function(arr) {

  n <- length(arr)
  run <- 32

  for (i in seq(1, n, by = run)) {
    arr <- insertion_sort(arr, i, min(i + run - 1, n))
  }

  size <- run

  while (size < n) {

    for (left in seq(1, n, by = 2 * size)) {

      mid <- left + size - 1
      right <- min(left + 2 * size - 1, n)

      if (mid < right) {
        arr <- merge(arr, left, mid, right)
      }

    }

    size <- size * 2

  }

  return(arr)

}

data <- c(45, 12, 78, 34, 23, 56, 89, 1, 9, 67)
print(tim_sort(data))

Seeing Tim Sort handle more data helps beginners trust the algorithm and understand its scalability.

Program 9: Tim Sort handling negative and floating-point numbers

Tim Sort naturally supports negative and decimal values, and this final program shows it clearly.

insertion_sort <- function(arr, left, right) {

  for (i in (left + 1):right) {

    key <- arr[i]
    j <- i - 1

    while (j >= left && arr[j] > key) {
      arr[j + 1] <- arr[j]
      j <- j - 1
    }

    arr[j + 1] <- key

  }

  return(arr)

}

merge <- function(arr, l, m, r) {

  left <- arr[l:m]
  right <- arr[(m + 1):r]
  i <- j <- 1
  k <- l

  while (i <= length(left) && j <= length(right)) {

    if (left[i] <= right[j]) {

      arr[k] <- left[i]
      i <- i + 1

    } else {

      arr[k] <- right[j]
      j <- j + 1

    }

    k <- k + 1

  }

  while (i <= length(left)) {

    arr[k] <- left[i]
    i <- i + 1
    k <- k + 1

  }

  while (j <= length(right)) {

    arr[k] <- right[j]
    j <- j + 1
    k <- k + 1

  }

  return(arr)

}

tim_sort <- function(arr) {

  n <- length(arr)
  run <- 32

  for (i in seq(1, n, by = run)) {
    arr <- insertion_sort(arr, i, min(i + run - 1, n))
  }

  size <- run

  while (size < n) {

    for (left in seq(1, n, by = 2 * size)) {

      mid <- left + size - 1
      right <- min(left + 2 * size - 1, n)

      if (mid < right) {
        arr <- merge(arr, left, mid, right)
      }

    }

    size <- size * 2

  }

  return(arr)

}

data <- c(-3.5, 2.1, -7.8, 4.6, 0.0, 1.9)
print(tim_sort(data))

This confirms that Tim Sort works well with real-world numeric data without any extra changes.

Frequently Asked Questions (FAQ)

This section answers common beginner questions about Tim Sort in R in a simple and friendly way.

Q1. Why is Tim Sort so popular?
Tim Sort is fast, stable, and works extremely well on real-world data that is often partially sorted.

Q2. Is Tim Sort better than Quick Sort?
In many practical cases yes, especially when data is already somewhat ordered, but both have their uses.

Q3. Does R use Tim Sort internally?
R uses optimized sorting methods written in C, but learning Tim Sort in R is great for understanding how modern algorithms work.

Q4. Is Tim Sort hard to learn for beginners?
It looks complex at first, but when broken into insertion sort and merge steps, it becomes much easier to understand.

Conclusion

Tim Sort is a powerful and modern sorting algorithm that shows how simple ideas can be combined to create something very efficient. By learning Tim Sort in R, beginners gain insight into how real-world sorting works behind the scenes.

Practicing these programs will help you become more confident with R, loops, functions, and algorithm design. Keep experimenting with different data and enjoy exploring classic algorithms that continue to shape modern programming.

Scroll to Top