Tim Sort is a highly efficient sorting algorithm that combines ideas from Merge Sort and Insertion Sort. It was originally designed to handle real-world data efficiently and is used in popular programming languages like Python and Java. The algorithm divides the array into small segments called “runs,” sorts each run using Insertion Sort, and then merges them together using a Merge Sort approach. This hybrid approach makes Tim Sort very fast and stable, even when data is partially sorted.
with hands-on learning.
get the skills and confidence to land your next move.
Learning Tim Sort is important because it shows beginners how combining multiple algorithms can create a highly optimized solution. It is widely used in real-world applications like sorting data in databases, spreadsheets, and large datasets where performance and stability matter. By understanding Tim Sort in JavaScript, beginners get insight into advanced sorting techniques while practicing practical coding skills.
Program 1: Basic Tim Sort implementation
This program demonstrates a simple implementation of Tim Sort in JavaScript. It uses Insertion Sort for small runs and merges them step by step.
function insertionSort(arr, left, right) {
for (let i = left + 1; i <= right; i++) {
let temp = arr[i];
let j = i - 1;
while (j >= left && arr[j] > temp) {
arr[j + 1] = arr[j];
j--;
}
arr[j + 1] = temp;
}
}
function merge(arr, left, mid, right) {
let len1 = mid - left + 1;
let len2 = right - mid;
let leftArr = [];
let rightArr = [];
for (let i = 0; i < len1; i++) leftArr[i] = arr[left + i];
for (let i = 0; i < len2; i++) rightArr[i] = arr[mid + 1 + i];
let i = 0, j = 0, k = left;
while (i < len1 && j < len2) {
if (leftArr[i] <= rightArr[j]) arr[k++] = leftArr[i++];
else arr[k++] = rightArr[j++];
}
while (i < len1) arr[k++] = leftArr[i++];
while (j < len2) arr[k++] = rightArr[j++];
}
function timSort(arr) {
const RUN = 32;
let n = arr.length;
for (let i = 0; i < n; i += RUN) {
insertionSort(arr, i, Math.min(i + RUN - 1, n - 1));
}
for (let size = RUN; size < n; size *= 2) {
for (let left = 0; left < n; left += 2 * size) {
let mid = Math.min(n - 1, left + size - 1);
let right = Math.min((left + 2 * size - 1), (n - 1));
if (mid < right) merge(arr, left, mid, right);
}
}
return arr;
}
let numbers = [5, 21, 7, 23, 19, 1, 10, 12];
console.log("Sorted array:", timSort(numbers));This program first sorts small chunks of the array using Insertion Sort, which is efficient for small datasets. Then it merges these chunks together using a Merge Sort approach. Beginners can understand Tim Sort as sorting small parts first and combining them gradually, which makes it stable and efficient.
Program 2: Tim Sort with custom run size
This version allows adjusting the run size for experimentation, helping beginners see how run length affects performance.
function insertionSort(arr, left, right) {
for (let i = left + 1; i <= right; i++) {
let temp = arr[i];
let j = i - 1;
while (j >= left && arr[j] > temp) {
arr[j + 1] = arr[j];
j--;
}
arr[j + 1] = temp;
}
}
function merge(arr, left, mid, right) {
let len1 = mid - left + 1;
let len2 = right - mid;
let leftArr = [];
let rightArr = [];
for (let i = 0; i < len1; i++) leftArr[i] = arr[left + i];
for (let i = 0; i < len2; i++) rightArr[i] = arr[mid + 1 + i];
let i = 0, j = 0, k = left;
while (i < len1 && j < len2) {
if (leftArr[i] <= rightArr[j]) arr[k++] = leftArr[i++];
else arr[k++] = rightArr[j++];
}
while (i < len1) arr[k++] = leftArr[i++];
while (j < len2) arr[k++] = rightArr[j++];
}
function timSortCustomRun(arr, RUN = 16) {
const n = arr.length;
for (let i = 0; i < n; i += RUN) {
insertionSort(arr, i, Math.min(i + RUN - 1, n - 1));
}
for (let size = RUN; size < n; size *= 2) {
for (let left = 0; left < n; left += 2 * size) {
let mid = Math.min(n - 1, left + size - 1);
let right = Math.min((left + 2 * size - 1), n - 1);
if (mid < right) merge(arr, left, mid, right);
}
}
return arr;
}
let values = [34, 8, 64, 51, 32, 21, 7, 12];
console.log("Sorted array:", timSortCustomRun(values));Here, adjusting the run size allows experimenting with how small chunks of the array are sorted. Beginners can learn how algorithm parameters affect efficiency. This is useful when working with different types of data, such as partially sorted or random arrays.
Program 3: Tim Sort in descending order
This program demonstrates sorting in descending order by changing comparison operators in both insertion and merge steps.
function insertionSortDesc(arr, left, right) {
for (let i = left + 1; i <= right; i++) {
let temp = arr[i];
let j = i - 1;
while (j >= left && arr[j] < temp) {
arr[j + 1] = arr[j];
j--;
}
arr[j + 1] = temp;
}
}
function mergeDesc(arr, left, mid, right) {
let len1 = mid - left + 1;
let len2 = right - mid;
let leftArr = [];
let rightArr = [];
for (let i = 0; i < len1; i++) leftArr[i] = arr[left + i];
for (let i = 0; i < len2; i++) rightArr[i] = arr[mid + 1 + i];
let i = 0, j = 0, k = left;
while (i < len1 && j < len2) {
if (leftArr[i] >= rightArr[j]) arr[k++] = leftArr[i++];
else arr[k++] = rightArr[j++];
}
while (i < len1) arr[k++] = leftArr[i++];
while (j < len2) arr[k++] = rightArr[j++];
}
function timSortDesc(arr) {
const RUN = 32;
let n = arr.length;
for (let i = 0; i < n; i += RUN) {
insertionSortDesc(arr, i, Math.min(i + RUN - 1, n - 1));
}
for (let size = RUN; size < n; size *= 2) {
for (let left = 0; left < n; left += 2 * size) {
let mid = Math.min(n - 1, left + size - 1);
let right = Math.min((left + 2 * size - 1), n - 1);
if (mid < right) mergeDesc(arr, left, mid, right);
}
}
return arr;
}
let scores = [50, 20, 40, 10, 30];
console.log("Sorted array (descending):", timSortDesc(scores));This program simply reverses the comparison logic. Beginners can see how minor changes in sorting conditions can reverse the order. It is useful for ranking systems or leaderboards.
Program 4: Tim Sort using reusable helper functions
This version demonstrates clean and reusable helper functions to make the code easier to integrate into other projects.
function timSortUtility(arr, RUN = 32) {
function insertionSortHelper(arr, left, right) {
for (let i = left + 1; i <= right; i++) {
let temp = arr[i];
let j = i - 1;
while (j >= left && arr[j] > temp) {
arr[j + 1] = arr[j];
j--;
}
arr[j + 1] = temp;
}
}
function mergeHelper(arr, left, mid, right) {
let leftArr = arr.slice(left, mid + 1);
let rightArr = arr.slice(mid + 1, right + 1);
let i = 0, j = 0, k = left;
while (i < leftArr.length && j < rightArr.length) {
if (leftArr[i] <= rightArr[j]) arr[k++] = leftArr[i++];
else arr[k++] = rightArr[j++];
}
while (i < leftArr.length) arr[k++] = leftArr[i++];
while (j < rightArr.length) arr[k++] = rightArr[j++];
}
let n = arr.length;
for (let i = 0; i < n; i += RUN) {
insertionSortHelper(arr, i, Math.min(i + RUN - 1, n - 1));
}
for (let size = RUN; size < n; size *= 2) {
for (let left = 0; left < n; left += 2 * size) {
let mid = Math.min(n - 1, left + size - 1);
let right = Math.min((left + 2 * size - 1), n - 1);
if (mid < right) mergeHelper(arr, left, mid, right);
}
}
return arr;
}
let items = [12, 7, 25, 19, 1, 30];
console.log("Sorted array:", timSortUtility(items));This program emphasizes modularity, making the algorithm easier to read and maintain. Beginners will find it easier to follow and reuse these helper functions in other projects.
Program 5: Tim Sort with dynamic run size for experimentation
This example demonstrates how to experiment with different run sizes to see how it affects performance.
function timSortUtility(arr, RUN = 32) {
function insertionSortHelper(arr, left, right) {
for (let i = left + 1; i <= right; i++) {
let temp = arr[i];
let j = i - 1;
while (j >= left && arr[j] > temp) {
arr[j + 1] = arr[j];
j--;
}
arr[j + 1] = temp;
}
}
function mergeHelper(arr, left, mid, right) {
let leftArr = arr.slice(left, mid + 1);
let rightArr = arr.slice(mid + 1, right + 1);
let i = 0, j = 0, k = left;
while (i < leftArr.length && j < rightArr.length) {
if (leftArr[i] <= rightArr[j]) arr[k++] = leftArr[i++];
else arr[k++] = rightArr[j++];
}
while (i < leftArr.length) arr[k++] = leftArr[i++];
while (j < rightArr.length) arr[k++] = rightArr[j++];
}
let n = arr.length;
for (let i = 0; i < n; i += RUN) {
insertionSortHelper(arr, i, Math.min(i + RUN - 1, n - 1));
}
for (let size = RUN; size < n; size *= 2) {
for (let left = 0; left < n; left += 2 * size) {
let mid = Math.min(n - 1, left + size - 1);
let right = Math.min((left + 2 * size - 1), n - 1);
if (mid < right) mergeHelper(arr, left, mid, right);
}
}
return arr;
}
let randomArray = [34, 8, 64, 51, 32, 21, 7, 12];
console.log("Sorted array with run size 8:", timSortUtility([...randomArray], 8));
console.log("Sorted array with run size 16:", timSortUtility([...randomArray], 16));By changing the run size, beginners can observe how Tim Sort behaves on different datasets. It teaches the value of tweaking parameters for optimization.
Frequently Asked Questions (FAQ)
This section answers common beginner questions about Tim Sort in JavaScript in a simple and friendly way.
Q1. What is Tim Sort in JavaScript?
Tim Sort is a hybrid sorting algorithm that combines Insertion Sort and Merge Sort to efficiently sort arrays.
Q2. Why is Tim Sort efficient?
It is optimized for real-world data, using small runs sorted with Insertion Sort and merging them efficiently, which reduces unnecessary comparisons.
Q3. Can Tim Sort handle partially sorted data well?
Yes, Tim Sort is very efficient when the data is partially sorted, which is common in real applications.
Q4. Is Tim Sort stable?
Yes, Tim Sort maintains the relative order of equal elements, making it a stable sort.
Q5. Should beginners learn Tim Sort?
Yes, learning Tim Sort introduces beginners to hybrid algorithms and teaches how combining simple strategies can create powerful solutions.
Conclusion
Tim Sort is a practical, efficient, and stable sorting algorithm that is widely used in modern programming languages. It demonstrates how combining simple techniques like Insertion Sort and Merge Sort can create a highly optimized solution.
For beginners, practicing Tim Sort helps build an understanding of advanced algorithm design, optimization strategies, and the importance of stability in sorting. Experimenting with run sizes, different datasets, and sorting orders will strengthen your JavaScript skills and make you confident in implementing real-world sorting algorithms.




