Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
sort.h
Go to the documentation of this file.
1#ifndef ROUTING_KIT_SORT_H
2#define ROUTING_KIT_SORT_H
3
5
6#include <vector>
7#include <assert.h>
8#include <algorithm>
9#include <functional>
10
11namespace RoutingKit{
12
13//
14// A sort permutation p of a vector v is a permutation such that
15// v[p[0]] <= v[p[1]] <= v[p[2]] <= ... . Applying a sort permutation p of v to
16// v yields a sorted vector.
17//
18// The functions in this header follow the following naming sheme:
19//
20// 1) compute_[inverse_][stable_]sort_using_[(key|less|comparator](vector, ...order...)
21// 2) [stable_]sort_using_[key|less|comparator](vector, ...order...)
22// 3) is_sorted_using_[key|less|comparator](vector, ...order...)
23//
24//
25// The functionality is explained as following:
26//
27// * The functions of category 1 compute sort permutations but do not actually
28// sort any array. The sorting is done by applying the resulting permutation
29// to one or more vectors.
30// * The functions of category 2 copy their argument vector, sort the copy and
31// return it. If an rvalue vector is given as parameter then the copy is
32// omitted.
33// * The functions of category 3 sort their argument array inplace.
34// * The functions of category 4 do not sort anything but check whether their
35// argument array is sorted.
36// * "inverse" indicates that not a sort permutation but its inverse is
37// computed. In combination with the _using_key function it is slightly
38// faster to compute an inverse sort permutation and then to use
39// apply_inverse_permutation then to compute a sort permutation and to use
40// apply_permutation.
41// * "stable" indicates that the relative order of values that compare equally
42// is not changed.
43// * "key" indicates that elements are sorted using bucket sort. All functions
44// take a (key_count, get_key) pair of parameters to specify the order.
45// get_key is a function object that must map every element onto a value in
46// [0,key_count). get_key is assumed to have a quick execution and is
47// called several times per sort operation. However, get_key is never
48// copied.
49// * "comparator" indicates that an STL like comparator is used and needs to
50// be passed to every function.
51// * "less" indicates that < is used for comparision. No order paramters need
52// to be passed to the functions.
53//
54
55template<class T, class C>
56std::vector<unsigned> compute_stable_sort_permutation_using_comparator(const std::vector<T>&v, const C&is_less){
57 std::vector<unsigned>p = identity_permutation(v.size());
58 std::stable_sort(
59 p.begin(), p.end(),
60 [&](unsigned l, unsigned r){
61 return is_less(v[l], v[r]);
62 }
63 );
64 return p; // NVRO
65}
66
67template<class T, class C>
68std::vector<T>stable_sort_using_comparator(const std::vector<T>&v, const C&is_less){
69 std::vector<T>r = v;
70 std::stable_sort(r.begin(), r.end(), is_less);
71 return r; // NVRO
72}
73
74template<class T, class C>
75std::vector<T>stable_sort_using_comparator(std::vector<T>&&v, const C&is_less){
76 std::stable_sort(v.begin(), v.end(), is_less);
77 return std::move(v); // NVRO
78}
79
80template<class T, class C>
81std::vector<unsigned> compute_sort_permutation_using_comparator(const std::vector<T>&v, const C&is_less){
82 std::vector<unsigned>p = identity_permutation(v.size());
83 std::sort(
84 p.begin(), p.end(),
85 [&](unsigned l, unsigned r){
86 return is_less(v[l], v[r]);
87 }
88 );
89 return p; // NVRO
90}
91
92template<class T, class C>
93std::vector<T>sort_using_comparator(const std::vector<T>&v, const C&is_less){
94 std::vector<T>r = v;
95 std::sort(r.begin(), r.end(), is_less);
96 return r; // NVRO
97}
98
99template<class T, class C>
100std::vector<T>sort_using_comparator(std::vector<T>&&v, const C&is_less){
101 std::sort(v.begin(), v.end(), is_less);
102 return std::move(v); // NVRO
103}
104
105
106template<class T, class C>
107bool is_sorted_using_comparator(const std::vector<T>&v, const C&is_less){
108 for(unsigned i=1; i<v.size(); ++i)
109 if(is_less(v[i], v[i-1]))
110 return false;
111 return true;
112}
113
114
115template<class T, class C>
116std::vector<unsigned> compute_inverse_sort_permutation_using_comparator(const std::vector<T>&v, const C&is_less){
118}
119
120template<class T, class C>
121std::vector<unsigned> compute_inverse_stable_sort_permutation_using_comparator(const std::vector<T>&v, const C&is_less){
123}
124
125
126
127namespace detail{
129
130 template<class T, class K>
131 std::vector<unsigned>compute_key_pos(const std::vector<T>&v, unsigned key_count, const K&get_key){
132 std::vector<unsigned>key_pos(key_count, 0);
133 for(unsigned i=0; i<v.size(); ++i){
134 unsigned k = get_key(v[i]);
135 assert(k <= key_count && "key is too large");
136 ++key_pos[k];
137 }
138 unsigned sum = 0;
139 for(unsigned i=0; i<key_count; ++i){
140 unsigned tmp = sum + key_pos[i];
141 key_pos[i] = sum;
142 sum = tmp;
143 }
144 return key_pos; // NVRO
145 }
146
147 template<class K>
149 explicit CompareByKey(unsigned n, const K&k):get_key(k){
150 #ifndef NDEBUG
151 key_count = n;
152 #else
153 (void)n;
154 #endif
155 }
156
157 template<class T>
158 bool operator()(const T&l, const T&r)const{
159 unsigned l_key = get_key(l);
160 assert(l_key < key_count);
161 unsigned r_key = get_key(r);
162 assert(r_key < key_count);
163 return l_key < r_key;
164 }
165
166 #ifndef NDEBUG
167 unsigned key_count;
168 #endif
169 const K&get_key;
170 };
171
172 template<class K>
174 return CompareByKey<K>(n, k);
175 }
176}
177
178namespace detail{
179 // Sorting by key uses bucket sort if the number of elements is
180 // not significantly smaller than the number of keys. Otherwise
181 // we use the sort by comparator function, which (at the time
182 // of writing this comment) forward to std::sort and
183 // std::stable_sort. Bucket sort is always stable whereas
184 // comparator-based sort is not. To avoid code dublication, we
185 // therefore have maybe_stable functions that take a compile time
186 // boolean which inidcates whether the fallback function should
187 // be stable.
188
189 template<bool is_stable, class T, class K>
190 std::vector<unsigned> compute_maybe_stable_sort_permutation_using_key(const std::vector<T>&v, unsigned key_count, const K&get_key){
191 std::vector<unsigned>p;
192
193 if(v.size() >= key_count / bucket_sort_min_key_to_element_ratio){
194 p.resize(v.size());
195 std::vector<unsigned>key_pos = detail::compute_key_pos(v, key_count, get_key);
196 for(unsigned i=0; i<v.size(); ++i){
197 unsigned k = get_key(v[i]);
198 assert(k <= key_count && "key is too large");
199 p[key_pos[k]] = i;
200 ++key_pos[k];
201 }
202 }else if(is_stable){
204 }else{
206 }
207 return p; // NVRO
208 }
209
210}
211
212template<class T, class K>
213std::vector<unsigned> compute_sort_permutation_using_key(const std::vector<T>&v, unsigned key_count, const K&get_key){
214 return detail::compute_maybe_stable_sort_permutation_using_key<false>(v, key_count, get_key);
215}
216
217template<class T, class K>
218std::vector<unsigned> compute_stable_sort_permutation_using_key(const std::vector<T>&v, unsigned key_count, const K&get_key){
219 return detail::compute_maybe_stable_sort_permutation_using_key<true>(v, key_count, get_key);
220}
221
222namespace detail{
223 template<bool is_stable, class T, class K>
224 std::vector<unsigned> compute_inverse_maybe_stable_sort_permutation_using_key(const std::vector<T>&v, unsigned key_count, const K&get_key){
225 std::vector<unsigned>p;
226 if(v.size() >= key_count / bucket_sort_min_key_to_element_ratio){
227 p.resize(v.size());
228 std::vector<unsigned>key_pos = detail::compute_key_pos(v, key_count, get_key);
229 for(unsigned i=0; i<v.size(); ++i){
230 unsigned k = get_key(v[i]);
231 assert(k <= key_count && "key is too large");
232 p[i] = key_pos[k];
233 ++key_pos[k];
234 }
235 } else if(is_stable){
237 }else{
239 }
240 return p; // NVRO
241 }
242}
243
244template<class T, class K>
245std::vector<unsigned> compute_inverse_sort_permutation_using_key(const std::vector<T>&v, unsigned key_count, const K&get_key){
246 return detail::compute_inverse_maybe_stable_sort_permutation_using_key<false>(v, key_count, get_key);
247}
248
249template<class T, class K>
250std::vector<unsigned> compute_inverse_stable_sort_permutation_using_key(const std::vector<T>&v, unsigned key_count, const K&get_key){
251 return detail::compute_inverse_maybe_stable_sort_permutation_using_key<true>(v, key_count, get_key);
252}
253
254namespace detail{
255 template<bool is_stable, class T, class K>
256 std::vector<T>maybe_stable_sort_using_key(const std::vector<T>&v, unsigned key_count, const K&get_key){
257 std::vector<T>r;
258
259 if(v.size() >= key_count / bucket_sort_min_key_to_element_ratio){
260 std::vector<unsigned>key_pos = detail::compute_key_pos(v, key_count, get_key);
261 r.resize(v.size());
262
263 for(unsigned i=0; i<v.size(); ++i){
264 unsigned k = get_key(v[i]);
265 assert(k <= key_count && "key is too large");
266 r[key_pos[k]] = v[i];
267 ++key_pos[k];
268 }
269 } else if(is_stable) {
271 } else {
272 r = sort_using_comparator(v, detail::make_compare_by_key(key_count, get_key));
273 }
274 return r; // NVRO
275 }
276
277 template<bool is_stable, class T, class K>
278 std::vector<T>maybe_stable_sort_using_key(std::vector<T>&&v, unsigned key_count, const K&get_key){
279 std::vector<T>r;
280 if(v.size() >= key_count / bucket_sort_min_key_to_element_ratio){
281 std::vector<unsigned>key_pos = detail::compute_key_pos(v, key_count, get_key);
282 r.resize(v.size());
283
284 for(unsigned i=0; i<v.size(); ++i){
285 unsigned k = get_key(v[i]);
286 assert(k <= key_count && "key is too large");
287 r[key_pos[k]] = std::move(v[i]);
288 ++key_pos[k];
289 }
290 } else if(is_stable) {
292 } else {
293 r = sort_using_comparator(v, detail::make_compare_by_key(key_count, get_key));
294 }
295 return r; // NVRO
296 }
297}
298
299template<class T, class K>
300std::vector<T>sort_using_key(const std::vector<T>&v, unsigned key_count, const K&get_key){
301 return detail::maybe_stable_sort_using_key<false>(v, key_count, get_key); // NVRO
302}
303
304template<class T, class K>
305std::vector<T>sort_using_key(std::vector<T>&&v, unsigned key_count, const K&get_key){
306 return detail::maybe_stable_sort_using_key<false>(std::move(v), key_count, get_key); // NVRO
307}
308
309template<class T, class K>
310std::vector<T>stable_sort_using_key(const std::vector<T>&v, unsigned key_count, const K&get_key){
311 return detail::maybe_stable_sort_using_key<true>(v, key_count, get_key); // NVRO
312}
313
314template<class T, class K>
315std::vector<T>stable_sort_using_key(std::vector<T>&&v, unsigned key_count, const K&get_key){
316 return detail::maybe_stable_sort_using_key<true>(std::move(v), key_count, get_key); // NVRO
317}
318
319
320template<class T, class K>
321bool is_sorted_using_key(const std::vector<T>&v, unsigned key_count, const K&get_key){
322 for(unsigned i=1; i<v.size(); ++i)
323 if(get_key(v[i]) < get_key(v[i-1]))
324 return false;
325 return true;
326}
327
328
329
330
331
332
333template<class T>
334std::vector<unsigned> compute_sort_permutation_using_less(const std::vector<T>&v){
335 return compute_sort_permutation_using_comparator(v, [](const T&l, const T&r){return l < r;});
336}
337
338template<class T>
339std::vector<unsigned> compute_stable_sort_permutation_using_less(const std::vector<T>&v){
340 return compute_stable_sort_permutation_using_comparator(v, [](const T&l, const T&r){return l < r;});
341}
342
343template<class T>
344std::vector<unsigned> compute_inverse_sort_permutation_using_less(const std::vector<T>&v){
346}
347
348template<class T>
352
353template<class T>
354std::vector<T>stable_sort_using_less(const std::vector<T>&v){
355 return stable_sort_using_comparator(v, [](const T&l, const T&r){return l < r;});
356}
357
358template<class T>
359std::vector<T>stable_sort_using_less(std::vector<T>&&v){
360 return stable_sort_using_comparator(std::move(v), [](const T&l, const T&r){return l < r;});
361}
362
363template<class T>
364std::vector<T>sort_using_less(const std::vector<T>&v){
365 return sort_using_comparator(v, [](const T&l, const T&r){return l < r;});
366}
367
368template<class T>
369std::vector<T>sort_using_less(std::vector<T>&&v){
370 return sort_using_comparator(std::move(v), [](const T&l, const T&r){return l < r;});
371}
372
373template<class T>
374bool is_sorted_using_less(const std::vector<T>&v){
375 return is_sorted_using_comparator(v, [](const T&l, const T&r){return l < r;});
376}
377
378} // RoutingKit
379
380#endif
std::vector< unsigned > compute_maybe_stable_sort_permutation_using_key(const std::vector< T > &v, unsigned key_count, const K &get_key)
Definition sort.h:190
CompareByKey< K > make_compare_by_key(unsigned n, const K &k)
Definition sort.h:173
std::vector< T > maybe_stable_sort_using_key(const std::vector< T > &v, unsigned key_count, const K &get_key)
Definition sort.h:256
std::vector< unsigned > compute_key_pos(const std::vector< T > &v, unsigned key_count, const K &get_key)
Definition sort.h:131
const unsigned bucket_sort_min_key_to_element_ratio
Definition sort.h:128
std::vector< unsigned > compute_inverse_maybe_stable_sort_permutation_using_key(const std::vector< T > &v, unsigned key_count, const K &get_key)
Definition sort.h:224
std::vector< unsigned > compute_stable_sort_permutation_using_key(const std::vector< T > &v, unsigned key_count, const K &get_key)
Definition sort.h:218
std::vector< unsigned > compute_inverse_sort_permutation_using_key(const std::vector< T > &v, unsigned key_count, const K &get_key)
Definition sort.h:245
bool is_sorted_using_less(const std::vector< T > &v)
Definition sort.h:374
std::vector< T > sort_using_comparator(const std::vector< T > &v, const C &is_less)
Definition sort.h:93
std::vector< T > stable_sort_using_comparator(const std::vector< T > &v, const C &is_less)
Definition sort.h:68
std::vector< unsigned > compute_sort_permutation_using_key(const std::vector< T > &v, unsigned key_count, const K &get_key)
Definition sort.h:213
bool is_sorted_using_comparator(const std::vector< T > &v, const C &is_less)
Definition sort.h:107
std::vector< T > stable_sort_using_key(const std::vector< T > &v, unsigned key_count, const K &get_key)
Definition sort.h:310
std::vector< T > sort_using_less(const std::vector< T > &v)
Definition sort.h:364
std::vector< T > stable_sort_using_less(const std::vector< T > &v)
Definition sort.h:354
std::vector< unsigned > invert_permutation(const std::vector< unsigned > &p)
std::vector< unsigned > compute_inverse_stable_sort_permutation_using_less(const std::vector< T > &v)
Definition sort.h:349
bool is_sorted_using_key(const std::vector< T > &v, unsigned key_count, const K &get_key)
Definition sort.h:321
std::vector< unsigned > compute_inverse_stable_sort_permutation_using_comparator(const std::vector< T > &v, const C &is_less)
Definition sort.h:121
std::vector< unsigned > compute_stable_sort_permutation_using_less(const std::vector< T > &v)
Definition sort.h:339
std::vector< unsigned > compute_inverse_stable_sort_permutation_using_key(const std::vector< T > &v, unsigned key_count, const K &get_key)
Definition sort.h:250
std::vector< T > sort_using_key(const std::vector< T > &v, unsigned key_count, const K &get_key)
Definition sort.h:300
std::vector< unsigned > compute_inverse_sort_permutation_using_less(const std::vector< T > &v)
Definition sort.h:344
std::vector< unsigned > compute_sort_permutation_using_less(const std::vector< T > &v)
Definition sort.h:334
std::vector< unsigned > identity_permutation(unsigned n)
std::vector< unsigned > compute_stable_sort_permutation_using_comparator(const std::vector< T > &v, const C &is_less)
Definition sort.h:56
std::vector< unsigned > compute_sort_permutation_using_comparator(const std::vector< T > &v, const C &is_less)
Definition sort.h:81
std::vector< unsigned > compute_inverse_sort_permutation_using_comparator(const std::vector< T > &v, const C &is_less)
Definition sort.h:116
bool operator()(const T &l, const T &r) const
Definition sort.h:158
CompareByKey(unsigned n, const K &k)
Definition sort.h:149