LIPH's C++ Codes
sort.h
Go to the documentation of this file.
1#ifndef LIPH_SORT_H_
2#define LIPH_SORT_H_
3
4#include <functional> // less
5#include <iterator> // iterator_traits
6#include <vector> // for bucket_sort
7
8namespace liph {
9
10template <class RandomIt, class Compare = std::less<typename std::iterator_traits<RandomIt>::value_type>>
11void bubble_sort(RandomIt first, RandomIt last, Compare comp = Compare()) {
12 using Distance = typename std::iterator_traits<RandomIt>::difference_type;
13 Distance n = std::distance(first, last);
14 for (Distance i = 0; i < n - 1; i++) {
15 for (Distance j = 0; j < n - 1; j++) {
16 if (!comp(*(first + j), *(first + j + 1))) {
17 std::swap(*(first + j), *(first + j + 1));
18 }
19 }
20 }
21}
22
23template <class RandomIt, class Compare = std::less<typename std::iterator_traits<RandomIt>::value_type>>
24void selection_sort(RandomIt first, RandomIt last, Compare comp = Compare()) {
25 using Distance = typename std::iterator_traits<RandomIt>::difference_type;
26 Distance n = std::distance(first, last);
27 for (Distance i = 0; i < n - 1; i++) {
28 Distance min_index = i;
29 for (Distance j = i + 1; j < n; j++) {
30 if (comp(*(first + j), *(first + min_index))) {
31 min_index = j;
32 }
33 }
34 if (min_index != i) {
35 std::swap(*(first + i), *(first + min_index));
36 }
37 }
38}
39
40template <class RandomIt, class Compare = std::less<typename std::iterator_traits<RandomIt>::value_type>>
41RandomIt partition(RandomIt first, RandomIt last, const Compare& comp = Compare()) {
42 using value_type = typename std::iterator_traits<RandomIt>::value_type;
43 value_type pivotkey = *first;
44 while (first != last) {
45 while (first != last && !comp(*(last - 1), pivotkey)) last--;
46 if (first != last) *first++ = *(last - 1);
47
48 while (first != last && comp(*first, pivotkey)) first++;
49 if (first != last) *(last - 1) = *first;
50 }
51 *first = pivotkey;
52 return first + 1;
53}
54
55template <class RandomIt, class Compare = std::less<typename std::iterator_traits<RandomIt>::value_type>>
56void quick_sort(RandomIt first, RandomIt last, Compare comp = Compare()) {
57 if (std::distance(first, last) > 1) {
58 RandomIt it = liph::partition(first, last, comp);
59 liph::quick_sort(first, it, comp);
60 liph::quick_sort(it, last, comp);
61 }
62}
63
65template <class RandomIt, class Compare = std::less<typename std::iterator_traits<RandomIt>::value_type>>
66void merge(RandomIt first, RandomIt mid, RandomIt last, Compare comp = Compare()) {
67 using value_type = typename std::iterator_traits<RandomIt>::value_type;
68 using Distance = typename std::iterator_traits<RandomIt>::difference_type;
69 Distance n = std::distance(first, last);
70
71 value_type *tmp = new value_type[n];
72 RandomIt i = first, j = mid;
73 value_type *k = tmp;
74 while (i < mid && j < last) {
75 if (comp(*i, *j))
76 *k++ = *i++;
77 else
78 *k++ = *j++;
79 }
80
81 while (i < mid) *k++ = *i++;
82 while (j < last) *k++ = *j++;
83
84 std::copy(tmp, tmp + n, first);
85 delete[] tmp;
86}
87
88template <class RandomIt, class Compare = std::less<typename std::iterator_traits<RandomIt>::value_type>>
89void merge_sort(RandomIt first, RandomIt last, Compare comp = Compare()) {
90 using Distance = typename std::iterator_traits<RandomIt>::difference_type;
91 Distance n = std::distance(first, last);
92 if (n <= 1) return;
93
94 RandomIt mid = first + n / 2;
95 liph::merge_sort(first, mid, comp);
96 liph::merge_sort(mid, last, comp);
97 liph::merge(first, mid, last, comp);
98}
99
100template <class RandomIt, class Compare = std::less<typename std::iterator_traits<RandomIt>::value_type>>
101void insert_sort(RandomIt first, RandomIt last, Compare comp = Compare()) {
102 using Distance = typename std::iterator_traits<RandomIt>::difference_type;
103 using value_type = typename std::iterator_traits<RandomIt>::value_type;
104 Distance n = std::distance(first, last);
105 // 从第二个元素起,小于前一个元素才需要插入
106 for (Distance i = 1; i < n; i++) {
107 if (comp(*(first + i), *(first + i - 1))) {
108 value_type x = *(first + i);
109 Distance j;
110 for (j = i - 1; j >= 0 && comp(x, *(first + j)); j--) *(first + j + 1) = *(first + j);
111 *(first + j + 1) = x;
112 }
113 }
114}
115
118template <class RandomIt, class Distance,
119 class Compare = std::less<typename std::iterator_traits<RandomIt>::value_type>>
120void shell_insert(RandomIt first, RandomIt last, Distance dk, Compare comp = Compare()) {
121 using value_type = typename std::iterator_traits<RandomIt>::value_type;
122 Distance n = std::distance(first, last);
123 for (Distance i = 0; i < dk; i++) {
124 for (Distance j = i + dk; j < n; j += dk) {
125 if (comp(*(first + j), *(first + j - dk))) {
126 value_type x = *(first + j);
127 Distance k;
128 for (k = j - dk; k >= 0 && comp(x, *(first + k)); k -= dk) {
129 *(first + k + dk) = *(first + k);
130 }
131 *(first + k + dk) = x;
132 }
133 }
134 }
135}
136
137template <class RandomIt, class Compare = std::less<typename std::iterator_traits<RandomIt>::value_type>>
138void shell_sort(RandomIt first, RandomIt last, Compare comp = Compare()) {
139 using Distance = typename std::iterator_traits<RandomIt>::difference_type;
140 Distance n = std::distance(first, last);
141 // dk 为增量,dk/2 上取整
142 for (Distance dk = (n + 1) / 2; dk > 1; dk = (dk + 1) / 2) {
143 shell_insert(first, last, dk, comp);
144 }
145 // same as insert_sort(first, last, comp);
146 shell_insert(first, last, 1, comp);
147}
148
149// 计数排序
150// 对于 A[0, n)中的每个元素 i, 0 <= i < max
151// n > 0, k > 0
152void counting_sort(int A[], int n, int max) {
153 // int count[max] = {0};
154 int *count = new int[max]{0};
155 for (int i = 0; i < n; i++) {
156 count[A[i]]++;
157 }
158
159 int index = 0;
160 for (int i = 0; i < max; i++) {
161 for (int j = 0; j < count[i]; j++) A[index++] = i;
162 }
163 delete[] count;
164}
165
166/*
167 * 基数排序
168 * A[0, n)中的每个元素不超过 d 位, 例如 d = 3 时,最大元素为999
169 * n > 0, d > 0
170 */
171void radix_sort(int A[], int n, int d) {
172 int *tmp = new int[n];
173 int count[10] = {0};
174 int factor = 1;
175 int flag = 0; // 标记对哪个数组排序
176 for (int i = 0; i < d; i++) {
177 // 从最低位开始排序
178 factor *= 10;
179 int *arr1 = (flag == 0 ? A : tmp);
180 int *arr2 = (flag == 0 ? tmp : A);
181 // clear count
182 for (int j = 0; j < 10; j++) {
183 count[j] = 0;
184 }
185
186 for (int j = 0; j < n; j++) {
187 int base = (arr1[j] % factor) / (factor / 10);
188 count[base]++;
189 }
190
191 // recount
192 for (int j = 9; j > 0; j--) count[j] = count[j - 1];
193 count[0] = 0;
194 for (int j = 1; j < 10; j++) count[j] += count[j - 1];
195
196 for (int j = 0; j < n; j++) {
197 int base = (arr1[j] % factor) / (factor / 10);
198 arr2[count[base]++] = arr1[j];
199 }
200
201 flag = 1 - flag;
202 }
203
204 if (flag) {
205 for (int i = 0; i < n; i++) {
206 A[i] = tmp[i];
207 }
208 }
209
210 delete[] tmp;
211}
212
213/*
214 * 桶排序
215 * 假定A[0, n) 均匀分布在[min, max) 区间,桶的个数为 m
216 * n > 0, min < max, m > 0
217 */
218void bucket_sort(int A[], int n, int min, int max, int m) {
219 std::vector<int> *tmp = new std::vector<int>[m];
220 int distance = max - min;
221 int count = (distance - 1) / m + 1; // ceil
222 for (int i = 0; i < n; i++) {
223 tmp[(A[i] - min) / count].emplace_back(A[i]);
224 }
225
226 int index = 0;
227 for (int i = 0; i < m; i++) {
228 liph::insert_sort(tmp[i].begin(), tmp[i].end());
229 for (size_t j = 0; j < tmp[i].size(); j++) {
230 A[index++] = tmp[i][j];
231 }
232 }
233
234 delete[] tmp;
235}
236
237} // namespace liph
238
239#endif // LIPH_SORT_H_
Definition: algorithm.h:10
void shell_insert(RandomIt first, RandomIt last, Distance dk, Compare comp=Compare())
Definition: sort.h:120
void shell_sort(RandomIt first, RandomIt last, Compare comp=Compare())
Definition: sort.h:138
void merge(RandomIt first, RandomIt mid, RandomIt last, Compare comp=Compare())
将有序的[first, mid) 和 [mid, last) 合并为有序的 [first, last)
Definition: sort.h:66
void bubble_sort(RandomIt first, RandomIt last, Compare comp=Compare())
Definition: sort.h:11
void bucket_sort(int A[], int n, int min, int max, int m)
Definition: sort.h:218
void radix_sort(int A[], int n, int d)
Definition: sort.h:171
void selection_sort(RandomIt first, RandomIt last, Compare comp=Compare())
Definition: sort.h:24
RandomIt partition(RandomIt first, RandomIt last, const Compare &comp=Compare())
Definition: sort.h:41
void quick_sort(RandomIt first, RandomIt last, Compare comp=Compare())
Definition: sort.h:56
void counting_sort(int A[], int n, int max)
Definition: sort.h:152
void merge_sort(RandomIt first, RandomIt last, Compare comp=Compare())
Definition: sort.h:89
void insert_sort(RandomIt first, RandomIt last, Compare comp=Compare())
Definition: sort.h:101