1
1
package sorting
2
2
3
- import java.lang.Integer .min
3
+ import kotlin.math .min
4
4
5
5
/* *
6
- * Tim sort algorithm
7
6
*
8
- * the best time: n
9
- * average time: n * log(n)
7
+ * Tim Sort is a hybrid sorting algorithm derived from merge sort and insertion sort
8
+ *
9
+ * used by Python’s sorted() and list.sort() functions, which was designed to perform well on
10
+ *
11
+ * many kinds of real-world data.
12
+ *
10
13
* worst time: n * log(n)
14
+ * best time: n
15
+ * average time: n * log(n)
11
16
*
12
17
* amount of memory: n
13
18
*
14
19
*/
15
20
16
- fun Array<Int>.timSort () {
17
- val size = size
18
- val minrun = minrun(size)
19
- var index = 0
20
- while (index < size) {
21
- insertionSort(this , index, min(index + minrun - 1 , size - 1 ))
22
- index + = minrun
23
- }
21
+ class TimSort {
24
22
25
- var mergingSize = minrun
26
- while (mergingSize < size) {
23
+ fun sort (array : Array <Int >) {
24
+ val arraySize = array.size
25
+ val minRunSize = minRunSize(arraySize)
27
26
28
- var left = 0
29
- while (left < size) {
30
- val middle = left + mergingSize - 1
31
- val right = min(left + 2 * mergingSize - 1 , size - 1 )
32
- if (middle < right) {
33
- merge(this , left, middle, right)
34
- }
35
- left + = mergingSize * 2
27
+ var i = 0
28
+ while (i < arraySize) {
29
+ insertionSort(array, i, min(i + minRunSize - 1 , arraySize - 1 ))
30
+ i + = minRunSize
36
31
}
37
32
38
- mergingSize * = 2
39
- }
40
- }
41
-
42
- private fun minrun (n : Int ) : Int {
43
- var addedValue = 0
44
- var size = n
45
- if (size >= 64 ) {
46
- addedValue = addedValue or (size and 1 )
47
- size = size.shr(1 )
48
- }
49
- return size + addedValue
50
- }
51
-
52
- private fun insertionSort (array : Array <Int >, left : Int , right : Int ) {
53
- var outerIndex = left + 1
54
- while (outerIndex <= right) {
55
- val temporaryValue = array[outerIndex]
56
- var innerIndex = outerIndex - 1
57
- while (innerIndex >= left && array[innerIndex] > temporaryValue) {
58
- array[innerIndex + 1 ] = array[innerIndex]
59
- innerIndex--
33
+ var mergingSize = minRunSize
34
+ while (mergingSize < arraySize) {
35
+ var start = 0
36
+ while (start < arraySize) {
37
+ val middle = start + mergingSize - 1
38
+ val end = min(start + 2 * mergingSize - 1 , arraySize - 1 )
39
+ if (middle < end) {
40
+ merge(array, start, middle, end)
41
+ }
42
+ start + = mergingSize * 2
43
+ }
44
+ mergingSize * = 2
60
45
}
61
- array[innerIndex + 1 ] = temporaryValue
62
- outerIndex++
63
46
}
64
- }
65
47
66
- private fun merge (array : Array <Int >, left : Int , middle : Int , right : Int ) {
67
- val leftLengthArray = middle - left + 1
68
- val rightLengthArray = right - middle
48
+ /* *
49
+ * Minrun is chosen from the range 32 to 64 inclusive, such that the size of the data, divided by minrun, is equal to,
50
+ * or slightly less than, a power of two. The final algorithm takes the six most significant bits of the size of the array,
51
+ * adds one if any of the remaining bits are set, and uses that result as the minrun.
52
+ * This algorithm works for all arrays, including those smaller than 64; for arrays of size 63 or less,
53
+ * this sets minrun equal to the array size and Timsort reduces to an insertion sort
54
+ */
55
+ private fun minRunSize (arraySize : Int ) : Int {
56
+ var result = 0
57
+ var size = arraySize
58
+ while (size >= 64 ) {
59
+ result = result or (size and 1 )
60
+ // shift one bit to the right until 6 significant bits remain
61
+ size = size shr 1
62
+ }
69
63
70
- var index = 0
71
- var leftArray = Array (leftLengthArray) { 0 }
72
- while (index < leftLengthArray) {
73
- leftArray[index] = array[left + index]
74
- index++
64
+ return size + result
75
65
}
76
66
77
- index = 0
78
- var rightArray = Array (rightLengthArray) { 0 }
79
- while (index < rightLengthArray) {
80
- rightArray[index] = array[middle + 1 + index]
81
- index++
67
+ private fun insertionSort (array : Array <Int >, start : Int , end : Int ) {
68
+ var i = start + 1
69
+ while (i <= end) {
70
+ val current = array[i]
71
+ var j = i - 1
72
+ while (j >= start && array[j] > current) {
73
+ array[j + 1 ] = array[j]
74
+ j--
75
+ }
76
+ array[j + 1 ] = current
77
+ i++
78
+ }
82
79
}
83
80
84
- var leftArrayIndex = 0
85
- var rightArrayIndex = 0
86
- index = 0
87
-
88
- while (leftArrayIndex < leftLengthArray && rightArrayIndex < rightLengthArray) {
89
- if (leftArray[leftArrayIndex] <= rightArray[rightArrayIndex]) {
90
- array[index] = leftArray[leftArrayIndex]
91
- leftArrayIndex++
92
- } else {
93
- array[index] = rightArray[rightArrayIndex]
94
- rightArrayIndex++
81
+ private fun merge (array : Array <Int >, start : Int , middle : Int , end : Int ) {
82
+ val leftSize = middle - start + 1
83
+ val rightSize = end - middle
84
+
85
+ var i = 0
86
+ val leftArray = Array (leftSize) { 0 }
87
+ while (i < leftSize) {
88
+ leftArray[i] = array[start + i]
89
+ i++
95
90
}
96
- index++
97
- }
98
91
99
- while (leftArrayIndex < leftLengthArray) {
100
- array[index] = leftArray[leftArrayIndex]
101
- leftArrayIndex++
102
- index++
103
- }
92
+ i = 0
93
+ val rightArray = Array (rightSize) { 0 }
94
+ while (i < rightSize) {
95
+ rightArray[i] = array[middle + i + 1 ]
96
+ i++
97
+ }
98
+
99
+ i = 0
100
+ var j = 0
101
+ var k = start
102
+ while (i < leftSize && j < rightSize) {
103
+ if (leftArray[i] <= rightArray[j]) {
104
+ array[k] = leftArray[i]
105
+ i++
106
+ } else {
107
+ array[k] = rightArray[j]
108
+ j++
109
+ }
110
+ k++
111
+ }
112
+
113
+ while (i < leftSize) {
114
+ array[k] = leftArray[i]
115
+ i++
116
+ k++
117
+ }
104
118
105
- while (rightArrayIndex < rightLengthArray) {
106
- array[index] = rightArray[rightArrayIndex]
107
- rightArrayIndex++
108
- index++
119
+ while (j < rightSize) {
120
+ array[k] = rightArray[j]
121
+ j++
122
+ k++
123
+ }
109
124
}
125
+
110
126
}
0 commit comments