-
Notifications
You must be signed in to change notification settings - Fork 0
/
timsort.cpp
102 lines (93 loc) · 3.97 KB
/
timsort.cpp
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
#include "timsort.h"
void merge(std::vector<int> &inputArray, std::vector<Part> &parts, bool isXY, std::vector<int> &tmp) {
Part f = parts[parts.size() - dy]; //берет предпоследний элемент
Part s = isXY ? parts[parts.size() - dx] : parts[parts.size() - dz]; // берет одного из соседов предпоследнего элемента
if (f.beg > s.beg) {
std::swap(f, s);
}
int posF = 0, posS = s.beg, pos = f.beg - 1;
int lstF = f.len, lstS = s.beg + s.len;
copy(inputArray.begin() + f.beg + posF, inputArray.begin() + f.beg + lstF, tmp.begin()); // запись предпоследнего в tmp
int fAmount = 0, sAmount = 0; //длина подпоследовательности
for (size_t i = 0; posF < lstF && posS < lstS; ++i) { //пока какая-нибудь из частей не дойдет до конца
if (tmp[posF] < inputArray[posS]) { //если
inputArray[++pos] = tmp[posF++];
++fAmount;
sAmount = 0;
if (fAmount == 7) {
if (*(tmp.begin() + lstF) > inputArray[posS]) {
copy(tmp.begin() + posF, tmp.begin() + lstF, inputArray.begin() + pos + 1);
pos += lstF - posF;
posF += lstF - posF;
}
std::vector<int>::iterator it = upper_bound(tmp.begin() + posF, tmp.begin() + lstF, inputArray[posS]);
copy(tmp.begin() + posF, it, inputArray.begin() + pos + 1);
pos += it - (tmp.begin() + posF);
posF += it - (tmp.begin() + posF);
}
}
else {
inputArray[++pos] = inputArray[posS++];
fAmount = 0;
++sAmount;
if (sAmount == 7) {
if (*(inputArray.begin() + lstS) > tmp[posF]) {
copy(inputArray.begin() + posS, inputArray.begin() + lstS, inputArray.begin() + pos + 1);
pos += lstS - posS;
posS += lstS - posS;
}
std::vector<int>::iterator it = upper_bound(inputArray.begin() + posS, inputArray.begin() + lstS, tmp[posF]);
copy(inputArray.begin() + posS, it, inputArray.begin() + pos + 1);
pos += it - (inputArray.begin() + posS);
posS += it - (inputArray.begin() + posS);
}
}
}
copy(tmp.begin() + posF, tmp.begin() + lstF, inputArray.begin() + pos + 1);
}
void tryMerge(std::vector<int> &inputArray, std::vector<Part> &parts, std::vector<int> &tmp, bool isMerge) {
for (size_t i = 0; parts.size() > 1; ++i) {
int x = parts[parts.size() - dx].len;
int y = parts.size() < 2 ? 0 : parts[parts.size() - dy].len;
int z = parts.size() < 3 ? 0 : parts[parts.size() - dz].len;
if (parts.size() >= 3 && z <= x + y) {
if (z < x) {
//printVector(tmp);
merge(inputArray, parts, false, tmp);
//printVector(tmp);
parts[parts.size() - dz].len += parts[parts.size() - dy].len;
parts[parts.size() - dy] = parts[parts.size() - dx];
parts.pop_back();
} else {
//printVector(tmp);
merge(inputArray, parts, true, tmp);
//printVector(tmp);
parts[parts.size() - dy].len += parts[parts.size() - dx].len;
parts.pop_back();
}
} else if (isMerge || y <= x) {
merge(inputArray, parts, true, tmp);
parts[parts.size() - dy].len += parts[parts.size() - dx].len;
parts.pop_back();
} else {
break;
}
}
}
void timsort(std::vector<int> &inputArray, std::vector<Part>& parts, std::vector<int>& tmp, int partSize) {
int inputArrSize = inputArray.size();
//int partSize = getMinSize(inputArrSize);
#pragma omp parallel for
for (int i = 0; i < inputArrSize; i += partSize) {
std::sort(inputArray.begin()+i,inputArray.begin() + i + std::min(partSize, inputArrSize - i));
//radixsort(inputArray.begin()+i,inputArray.begin()+i + std::min(partSize, inputArrSize - i));
}
for (int i = 0; i < inputArrSize; i += partSize) {
parts.push_back(Part(i, std::min(partSize, inputArrSize - i)));
tryMerge(inputArray, parts, tmp);
}
for (size_t i = 0; parts.size() != 1; ++i) {
tryMerge(inputArray, parts, tmp, true);
}
//std::sort(inputArray.begin(),inputArray.end());
}