Skip to content

Commit 7f46135

Browse files
implemented TimSort
1 parent 0dcec9e commit 7f46135

File tree

2 files changed

+121
-0
lines changed

2 files changed

+121
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
package algorithms.sort
2+
3+
/// Hybrid sorting algorithm: Timsort
4+
/// Combines Insertion Sort for small partitions and Merge Sort for merging
5+
/// Example:
6+
/// val Arr = Array(5, 2, 9, 1, 5, 6)
7+
/// timSort(Arr, 64)
8+
/// println(Arr) // Returns (1, 2, 5, 5, 6, 9)
9+
/// Timsort runs in O(n log n) worst-case.
10+
def timSort(arr: Array[Int], k: Int = 64): Unit = {
11+
require(arr != null, "Input array must not be null") // Ensure valid input
12+
13+
val n = arr.length
14+
15+
// Step 1: Sort small chunks with Insertion Sort
16+
for (i <- 0 until n by k) {
17+
val end = Math.min(i + k, n)
18+
insertionSortInPlace(arr, i, end)
19+
}
20+
21+
// Step 2: Merge sorted chunks with Merge Sort
22+
var size = k
23+
while (size < n) {
24+
for (left <- 0 until n by 2 * size) {
25+
val mid = Math.min(left + size, n)
26+
val right = Math.min(left + 2 * size, n)
27+
28+
if (mid < right) merge(arr, left, mid, right)
29+
}
30+
size *= 2
31+
}
32+
}
33+
34+
// Helper function: Insertion Sort for a subarray
35+
private def insertionSortInPlace(arr: Array[Int], start: Int, end: Int): Unit = {
36+
for (i <- start + 1 until end) {
37+
val key = arr(i)
38+
var j = i - 1
39+
40+
while (j >= start && arr(j) > key) {
41+
arr(j + 1) = arr(j)
42+
j -= 1
43+
}
44+
arr(j + 1) = key
45+
}
46+
}
47+
48+
// Helper function: Merge two sorted subarrays
49+
private def merge(arr: Array[Int], left: Int, mid: Int, right: Int): Unit = {
50+
val leftArr = arr.slice(left, mid)
51+
val rightArr = arr.slice(mid, right)
52+
53+
var i = 0
54+
var j = 0
55+
var k = left
56+
57+
while (i < leftArr.length && j < rightArr.length) {
58+
if (leftArr(i) <= rightArr(j)) {
59+
arr(k) = leftArr(i)
60+
i += 1
61+
} else {
62+
arr(k) = rightArr(j)
63+
j += 1
64+
}
65+
k += 1
66+
}
67+
68+
while (i < leftArr.length) {
69+
arr(k) = leftArr(i)
70+
i += 1
71+
k += 1
72+
}
73+
74+
while (j < rightArr.length) {
75+
arr(k) = rightArr(j)
76+
j += 1
77+
k += 1
78+
}
79+
}
80+
81+
// Return version of Timsort
82+
def returnTimSort(arr: Array[Int], k: Int = 64): Array[Int] = {
83+
timSort(arr, k)
84+
arr
85+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package algorithms.sort
2+
3+
import algorithms.sort.timSort
4+
5+
import munit.*
6+
7+
class TimSortTest extends FunSuite {
8+
test("timSort sorts arrays correctly") {
9+
val arr = Array(4, 2, 1, 5, 6, 3, 7, 12, 8, 10, 9, 11)
10+
timSort(arr)
11+
assertEquals(arr.toSeq, Array.range(1, 13).toSeq)
12+
}
13+
test("timSort sorts arrays with negatives correctly") {
14+
val arr = Array(-1, 4, 2, 1, -4, 5, 6, 3, 0, 7, 12, -3, 8, 10, 9, -2, 11)
15+
timSort(arr)
16+
assertEquals(arr.toSeq, Array.range(-4, 13).toSeq)
17+
}
18+
19+
test("timSort sorts arrays with duplicates") {
20+
val arr = Array(4, 2, 1, 5, 3, 2)
21+
timSort(arr)
22+
assertEquals(arr.toSeq, Array(1, 2, 2, 3, 4, 5).toSeq)
23+
}
24+
25+
test("timSort handles singleton arrays") {
26+
val arr = Array(1)
27+
timSort(arr)
28+
assertEquals(arr.toSeq, Array(1).toSeq)
29+
}
30+
test("timSort-sort handles empty arrays") {
31+
val arr = Array.empty[Int]
32+
timSort(arr)
33+
assertEquals(arr.toSeq, Array.empty[Int].toSeq)
34+
}
35+
36+
}

0 commit comments

Comments
 (0)