-
Notifications
You must be signed in to change notification settings - Fork 0
/
algorithms_sort.h
362 lines (282 loc) · 10.8 KB
/
algorithms_sort.h
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
// algorithms_sort.h standart header - by jannik voss
/*
HEADER FILE INFORMATION:
language: C++11 not required
source: no source file needed
algorithms (quick overview):
bubble_sort
selection_sort
quick_sort
insertion_sort
shell_sort
comb_sort
heap_sort
functions:
template<class Fd_iter, class Less
= std::less<std::iterator_traits<Fd_iter>::value_type>>
void bubble_sort(Fd_iter first, Fd_iter last, Less cmp = Less())
template<class Fd_iter, class Less
= std::less<std::iterator_traits<Fd_iter>::value_type>>
void selection_sort(Fd_iter first, Fd_iter last, Less cmp = Less())
template<class Bd_iter, class Less
= std::less<std::iterator_traits<Bd_iter>::value_type>>
void quick_sort(Bd_iter first, Bd_iter last, Less cmp=Less())
template<class Bd_iter, class Less
= std::less<std::iterator_traits<Bd_iter>::value_type>>
void insertion_sort(Bd_iter first, Bd_iter last, Less cmp = Less())
template<class Bd_iter, class Less
= std::less<std::iterator_traits<Bd_iter>::value_type>>
void shell_sort(Bd_iter first, Bd_iter last, Less cmp = Less())
template<class Fd_iter, class Less
= std::less<std::iterator_traits<Fd_iter>::value_type>>
void comb_sort(Fd_iter first, Fd_iter last, Less cmp = Less())
template<class Rda_iter, class Less
= std::less<std::iterator_traits<Rda_iter>::value_type>>
void heap_sort(Rda_iter first, Rda_iter last, Less cmp = Less())
*/
#pragma once
#include <algorithm>
#include <iterator>
#include <functional>
namespace algo{
/*
TEMPLATE FUNCTION bubble_sort
order [_First, _Last) using a bubble sort algorithm.
further information: http://en.wikipedia.org/wiki/Bubble_sort
you can optionally use a binary function object class whose call returns
whether the its first argument compares less than the second.
requirements: Fd_iter is a forward-iterator type
complexity: ...
assertions: (assert(x))
Fd_iter is an STL-like forward iterator (std::forward_iterator_tag)
*/
// TEMPLATE FUNCTION Bubble_sort0 (simple version)
template<class Fd_iter, class Less>
void Bubble_sort0(Fd_iter first, Fd_iter last, Less cmp)
{ // order [_First, _Last)
typedef std::is_base_of<std::forward_iterator_tag,typename Fd_iter::iterator_category> ass_ty;
assert(typename ass_ty::value);
for(auto i = first; i != last; std::advance(i,1))
for(auto j = first; j < i; std::advance(j,1))
if(cmp(*i, *j)) // i<j
std::iter_swap(i, j);
}
// TEMPLATE FUNCTION Bubble_sort1 (optimized version)
template<class Fd_iter, class Less>
void Bubble_sort1(Fd_iter first, Fd_iter last, Less cmp)
{ // order [_First, _Last)
typedef std::is_base_of<std::forward_iterator_tag,typename Fd_iter::iterator_category> ass_ty;
assert(typename ass_ty::value);
// left (first+1) and right (last-1) element
const auto r = std::next(first,std::distance(first, last)-1);
const auto l = std::next(first);
Fd_iter i; // the loop variable
do {
auto newi = l;
for(auto j=first; j != r; std::advance(j,1))
{
const auto nj = std::next(j); // next element
if(cmp(*nj,*j)) // nj<j
{
std::iter_swap(j, nj);
newi = nj;
}
}
i = newi; // update the loop variable
} while(i!=l);
}
// TEMPLATE FUNCTION bubble_sort
template<class Fd_iter, class Less
= std::less<std::iterator_traits<Fd_iter>::value_type>>
void bubble_sort(Fd_iter first, Fd_iter last, Less cmp = Less())
{ // order [_First, _Last)
Bubble_sort1(first, last, cmp);
}
/*
TEMPLATE FUNCTION selection_sort
order [_First, _Last) using a selection sort algorithm.
further information: http://en.wikipedia.org/wiki/Selection_sort
you can optionally use a binary function object class whose call returns
whether the its first argument compares less than the second.
requirements: Fd_iter is a forward-iterator type
complexity: ...
assertions: (assert(x))
Fd_iter is an STL-like forward iterator (std::forward_iterator_tag)
*/
// TEMPLATE FUNCTION selection_sort
template<class Fd_iter, class Less
= std::less<std::iterator_traits<Fd_iter>::value_type>>
void selection_sort(Fd_iter first, Fd_iter last, Less cmp = Less())
{ // order [_First, _Last)
typedef std::is_base_of<std::forward_iterator_tag,typename Fd_iter::iterator_category> ass_ty;
assert(typename ass_ty::value);
for(auto i=first; i<last; std::advance(i,1))
{
auto min = std::min_element(i,last,cmp);
std::iter_swap(i,min);
}
}
/*
TEMPLATE FUNCTION quick_sort
order [_First, _Last) using a quick sort algorithm.
further information: http://en.wikipedia.org/wiki/Quick_sort
you can optionally use a binary function object class whose call returns
whether the its first argument compares less than the second.
requirements: Bd_iter is a bidirectional-iterator type
complexity: ...
assertions: (assert(x))
Bd_iter is an STL-like bidirectional iterator (std::bidirectional_iterator_tag)
*/
// TEMPLATE FUNCTION quick_sort
template<class Bd_iter, class Less
= std::less<std::iterator_traits<Bd_iter>::value_type>>
void quick_sort(Bd_iter first, Bd_iter last, Less cmp=Less())
{ // order [_First, _Last)
typedef std::is_base_of<std::bidirectional_iterator_tag,typename Bd_iter::iterator_category> ass_ty;
assert(typename ass_ty::value);
auto dist = std::distance(first,last);
if(dist < 2)
return;
// select pivot in the middle of the sequence
auto pivot = first;
std::advance(pivot, dist/2);
auto val = *pivot;
// select left (first) and right (last-1) element
auto l = first;
auto r = std::prev(last);
std::iter_swap(pivot, r); // swap the pivot element with the last element
// split the sequence into two parts
// ->values lower than the pivot element go to the left part
// ->values highter than the pivot element go to the right part
auto pivot_pos = l;
while(l != r)
{
if(cmp(*l,val))
{
std::iter_swap(l, pivot_pos);
std::advance(pivot_pos, 1);
}
std::advance(l, 1);
}
std::iter_swap(pivot_pos, r); // swap back the pivot element
// recursively call the function for both parts
quick_sort(first, pivot_pos, cmp);
quick_sort(std::next(pivot_pos), last, cmp);
}
/*
TEMPLATE FUNCTION insertion_sort
order [_First, _Last) using an insertion sort algorithm.
further information: http://en.wikipedia.org/wiki/Insertion_sort
you can optionally use a binary function object class whose call returns
whether the its first argument compares less than the second.
requirements: Bd_iter is a bidirectional-iterator type
complexity: ...
assertions: (assert(x))
Bd_iter is an STL-like bidirectional iterator (std::bidirectional_iterator_tag)
*/
// TEMPLATE FUNCTION insertion_sort
template<class Bd_iter, class Less
= std::less<std::iterator_traits<Bd_iter>::value_type>>
void insertion_sort(Bd_iter first, Bd_iter last, Less cmp = Less())
{ // order [_First, _Last)
typedef std::is_base_of<std::bidirectional_iterator_tag,typename Bd_iter::iterator_category> ass_ty;
assert(typename ass_ty::value);
for(auto i = std::next(first); i != last; std::advance(i,1))
for(auto j = i; j != first && cmp(*j,*std::prev(j)); std::advance(j,-1))
std::iter_swap(std::prev(j), j);
}
/*
TEMPLATE FUNCTION shell_sort
order [_First, _Last) using a shell sort algorithm.
shell sort is a modification of insertion sort.
further information: http://en.wikipedia.org/wiki/Shellsort
you can optionally use a binary function object class whose call returns
whether the its first argument compares less than the second.
requirements: Bd_iter is a bidirectional-iterator type
complexity: ...
gaps: 701,301,132,57,23,10,4,1
assertions: (assert(x))
Bd_iter is an STL-like bidirectional iterator (std::bidirectional_iterator_tag)
*/
// TEMPLATE FUNCTION shell_sort
template<class Bd_iter, class Less
= std::less<std::iterator_traits<Bd_iter>::value_type>>
void shell_sort(Bd_iter first, Bd_iter last, Less cmp = Less())
{ // order [_First, _Last)
typedef std::is_base_of<std::bidirectional_iterator_tag,typename Bd_iter::iterator_category> ass_ty;
assert(typename ass_ty::value);
typedef typename std::iterator_traits<Bd_iter>::difference_type diff_ty;
static const diff_ty gaps[8] = {701,301,132,57,23,10,4,1};
auto n = std::distance(first,last);
for(diff_ty g:gaps)
{
for(auto i=g; i<n; ++i)
{
auto t=*std::next(first,i);
diff_ty j=i;
for(; j>=g && cmp(t,*std::next(first,j-g)); j-=g)
*std::next(first,j) = *std::next(first,j-g);
*std::next(first,j) = t;
}
}
}
/*
TEMPLATE FUNCTION comb_sort
order [_First, _Last) using a comb sort algorithm.
comb sort is a modification of bubble sort.
further information: http://en.wikipedia.org/wiki/Comb_sort
you can optionally use a binary function object class whose call returns
whether the its first argument compares less than the second.
requirements: Fd_iter is a forward-iterator type
complexity: ...
assertions: (assert(x))
Fd_iter is an STL-like forward iterator (std::forward_iterator_tag)
*/
// TEMPLATE FUNCTION comb_sort
template<class Fd_iter, class Less
= std::less<std::iterator_traits<Fd_iter>::value_type>>
void comb_sort(Fd_iter first, Fd_iter last, Less cmp = Less())
{ // order [_First, _Last)
typedef std::is_base_of<std::forward_iterator_tag,typename Fd_iter::iterator_category> ass_ty;
assert(typename ass_ty::value);
typedef typename std::iterator_traits<Fd_iter>::difference_type diff_ty;
const diff_ty n = std::distance(first,last);
diff_ty step=n;
bool swapped;
do {
swapped = false; // reset the loop variable
if(step > 1) step = diff_ty(step/1.3); // shrink by factor 1.3
for(Fd_iter i=first, j=std::next(i,step);
i<std::next(first,n-step);
std::advance(i,1), std::advance(j,1)
){
if(cmp(*j,*i))
{
std::iter_swap(i, j);
swapped = true;
}
}
} while(swapped || step > 1);
}
/*
TEMPLATE FUNCTION heap_sort
order [_First, _Last) using a heap sort algorithm.
further information: http://en.wikipedia.org/wiki/Heapsort
you can optionally use a binary function object class whose call returns
whether the its first argument compares less than the second.
requirements: Rda_iter is a random-access-iterator type
complexity: ...
assertions: (assert(x))
Rd_iter is an STL-like random access iterator (std::random_access_iterator_tag)
*/
// TEMPLATE FUNCTION heap_sort
template<class Rda_iter, class Less
= std::less<std::iterator_traits<Rda_iter>::value_type>>
void heap_sort(Rda_iter first, Rda_iter last, Less cmp = Less())
{ // order [_First, _Last)
typedef std::is_base_of<std::random_access_iterator_tag,typename Rda_iter::iterator_category> ass_ty;
assert(typename ass_ty::value);
std::make_heap(first, last, cmp);
std::sort_heap(first, last, cmp);
}
};//end: namespace