-
Notifications
You must be signed in to change notification settings - Fork 0
/
TimSort.kt
110 lines (95 loc) · 2.68 KB
/
TimSort.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
package sorting
import java.lang.Integer.min
/**
* Tim sort algorithm
*
* the best time: n
* average time: n * log(n)
* worst time: n * log(n)
*
* amount of memory: n
*
*/
fun Array<Int>.timSort() {
val size = size
val minrun = minrun(size)
var index = 0
while (index < size) {
insertionSort(this, index, min(index + minrun - 1, size - 1))
index += minrun
}
var mergingSize = minrun
while (mergingSize < size) {
var left = 0
while (left < size) {
val middle = left + mergingSize - 1
val right = min(left + 2 * mergingSize - 1, size - 1)
if (middle < right) {
merge(this, left, middle, right)
}
left += mergingSize * 2
}
mergingSize *= 2
}
}
private fun minrun(n: Int) : Int {
var addedValue = 0
var size = n
if (size >= 64) {
addedValue = addedValue or (size and 1)
size = size.shr(1)
}
return size + addedValue
}
private fun insertionSort(array: Array<Int>, left: Int, right: Int) {
var outerIndex = left + 1
while (outerIndex <= right) {
val temporaryValue = array[outerIndex]
var innerIndex = outerIndex - 1
while (innerIndex >= left && array[innerIndex] > temporaryValue) {
array[innerIndex + 1] = array[innerIndex]
innerIndex--
}
array[innerIndex + 1] = temporaryValue
outerIndex++
}
}
private fun merge(array: Array<Int>, left: Int, middle: Int, right: Int) {
val leftLengthArray = middle - left + 1
val rightLengthArray = right - middle
var index = 0
var leftArray = Array(leftLengthArray) { 0 }
while (index < leftLengthArray) {
leftArray[index] = array[left + index]
index++
}
index = 0
var rightArray = Array(rightLengthArray) { 0 }
while (index < rightLengthArray) {
rightArray[index] = array[middle + 1 + index]
index++
}
var leftArrayIndex = 0
var rightArrayIndex = 0
index = 0
while (leftArrayIndex < leftLengthArray && rightArrayIndex < rightLengthArray) {
if (leftArray[leftArrayIndex] <= rightArray[rightArrayIndex]) {
array[index] = leftArray[leftArrayIndex]
leftArrayIndex++
} else {
array[index] = rightArray[rightArrayIndex]
rightArrayIndex++
}
index++
}
while (leftArrayIndex < leftLengthArray) {
array[index] = leftArray[leftArrayIndex]
leftArrayIndex++
index++
}
while (rightArrayIndex < rightLengthArray) {
array[index] = rightArray[rightArrayIndex]
rightArrayIndex++
index++
}
}