DeSiGNAR  0.5a
Data Structures General Library
sort.H
Go to the documentation of this file.
1 /*
2  This file is part of Designar.
3  Copyright (C) 2017 by Alejandro J. Mujica
4 
5  This program is free software: you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation, either version 3 of the License, or
8  (at your option) any later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18  Any user request of this software, write to
19 
20  Alejandro Mujica
21 
22  aledrums@gmail.com
23 */
24 
25 # ifndef DSGSORT_H
26 # define DSGSORT_H
27 
28 # include <array.H>
29 # include <list.H>
30 
31 namespace Designar
32 {
33 
34  template <typename T,
35  template <typename> class ArrayType,
36  class Cmp = std::less<T>>
37  lint_t binary_search(const ArrayType<T> &, const T &,
38  lint_t, lint_t, Cmp &);
39 
40  template <typename T,
41  template <typename> class ArrayType,
42  class Cmp = std::less<T>>
43  lint_t sequential_search(const ArrayType<T> &, const T &,
44  lint_t, lint_t, Cmp &);
45 
46  template <class ArrayType, class Cmp>
47  void insertion_sort(ArrayType &, lint_t, lint_t, Cmp &);
48 
49  template <typename ArrayType, class Cmp>
50  lint_t partition(ArrayType &, lint_t, lint_t, Cmp &);
51 
52  template <typename ArrayType, class Cmp>
53  void quicksort(ArrayType &, lint_t, lint_t, Cmp &);
54 
55  template <typename T, class Cmp>
56  void sift_up(T *, nat_t, nat_t, Cmp &);
57 
58  template <typename T, class Cmp>
59  void sift_down(T *, nat_t, nat_t, Cmp &);
60 
61  template <typename T, class Cmp>
62  std::tuple<NodeSLList<T>, typename NodeSLList<T>::Node *, NodeSLList<T>>
63  partition(NodeSLList<T> &, Cmp &);
64 
65  template <typename T, class Cmp>
66  void quicksort(NodeSLList<T> &, Cmp &);
67 
68  template <class Cmp>
69  std::tuple<DL, DL *, DL> partition(DL &, Cmp &);
70 
71  template <class Cmp>
72  void quicksort(DL &, Cmp &);
73 
74  template <class ArrayType>
75  ArrayType reverse(const ArrayType &);
76 
77  template <class SRCL, class TGTL>
78  TGTL reverse(const SRCL &);
79 
80  template <typename T, template <typename> class ArrayType, class Cmp>
81  lint_t binary_search(const ArrayType<T> & a, const T & k,
82  lint_t l, lint_t r, Cmp & cmp)
83  {
84  if (l > r)
85  return l;
86 
87  lint_t m = (l + r) / 2;
88 
89  if (cmp(k, a.at(m)))
90  return binary_search(a, k, l, m - 1, cmp);
91  else if (cmp(a.at(m), k))
92  return binary_search(a, k, m + 1, r, cmp);
93 
94  return m;
95  }
96 
97  template <typename T,
98  template <typename> class ArrayType,
99  class Cmp = std::less<T>>
100  inline lint_t binary_search(const ArrayType<T> & a, T & k,
101  lint_t l, lint_t r, Cmp && cmp = Cmp())
102  {
103  return binary_search<T, ArrayType, Cmp>(a, k, l, r, cmp);
104  }
105 
106  template <typename T,
107  template <typename> class ArrayType,
108  class Cmp = std::less<T>>
109  inline lint_t binary_search(const ArrayType<T> & a, const T & k,
110  Cmp & cmp)
111  {
112  return binary_search<T, ArrayType, Cmp>(a, k, 0, a.size() - 1, cmp);
113  }
114 
115  template <typename T,
116  template <typename> class ArrayType,
117  class Cmp = std::less<T>>
118  inline lint_t binary_search(const ArrayType<T> & a, const T & k,
119  Cmp && cmp = Cmp())
120  {
121  return binary_search<T, ArrayType, Cmp>(a, k, cmp);
122  }
123 
124  template <typename T, template <typename> class ArrayType, class Cmp>
125  lint_t sequential_search(const ArrayType<T> & a, const T & k,
126  lint_t l, lint_t r, Cmp & cmp)
127  {
128  lint_t i = l;
129 
130  while (i <= r and not cmp(k, a.at(i)))
131  ++i;
132 
133  return i;
134  }
135 
136  template <typename T,
137  template <typename> class ArrayType,
138  class Cmp = std::less<T>>
139  lint_t sequential_search(const ArrayType<T> & a, const T & k,
140  lint_t l, lint_t r, Cmp && cmp = Cmp())
141  {
142  return sequential_search<T, ArrayType, Cmp>(a, k, l, r, cmp);
143  }
144 
145  template <typename T,
146  template <typename> class ArrayType,
147  class Cmp = std::less<T>>
148  lint_t sequential_search(const ArrayType<T> & a, const T & k, Cmp & cmp)
149  {
150  return sequential_search<T, ArrayType, Cmp>(a, k, 0, a.size() - 1, cmp);
151  }
152 
153  template <typename T,
154  template <typename> class ArrayType,
155  class Cmp = std::less<T>>
156  lint_t sequential_search(const ArrayType<T> & a, const T & k,
157  Cmp && cmp = Cmp())
158  {
159  return sequential_search<T, ArrayType, Cmp>(a, k, cmp);
160  }
161 
162  template <class ArrayType, class Cmp>
163  void insertion_sort(ArrayType & a, lint_t l, lint_t r, Cmp & cmp)
164  {
165  for (lint_t i = l + 1; i <= r; ++i)
166  {
167  typename ArrayType::DataType data = std::move(a[i]);
168 
169  lint_t j = i;
170 
171  for ( ; j > l and cmp(data, a[j - 1]); --j)
172  a[j] = std::move(a[j - 1]);
173 
174  a[j] = std::move(data);
175  }
176  }
177 
178  template <class ArrayType,
179  class Cmp = std::less<typename ArrayType::DataType>> inline
180  void insertion_sort(ArrayType & a, lint_t l, lint_t r, Cmp && cmp = Cmp())
181  {
182  insertion_sort<ArrayType, Cmp>(a, l, r, cmp);
183  }
184 
185  template <class ArrayType, class Cmp>
186  inline void insertion_sort(ArrayType & a, lint_t size, Cmp & cmp)
187  {
188  insertion_sort(a, 0, size - 1, cmp);
189  }
190 
191  template <class ArrayType,
192  class Cmp = std::less<typename ArrayType::DataType>>
193  inline void insertion_sort(ArrayType & a, lint_t size, Cmp && cmp = Cmp())
194  {
195  insertion_sort<ArrayType, Cmp>(a, size, cmp);
196  }
197 
198  template <class ArrayType, class Cmp>
199  inline void insertion_sort(ArrayType & a, Cmp & cmp)
200  {
201  insertion_sort(a, a.size(), cmp);
202  }
203 
204  template <class ArrayType,
205  class Cmp = std::less<typename ArrayType::DataType>>
206  inline void insertion_sort(ArrayType & a, Cmp && cmp = Cmp())
207  {
208  insertion_sort<ArrayType, Cmp>(a, cmp);
209  }
210 
211  template <typename ArrayType, class Cmp>
212  inline lint_t select_pivot(ArrayType & a, lint_t l, lint_t r, Cmp & cmp)
213  {
214  assert(l <= r);
215 
216  lint_t m = (l + r) / 2;
217 
218  lint_t partial_min = cmp(a[l], a[m]) ? l : m;
219 
220  return cmp(a[partial_min], a[r]) ? partial_min : r;
221  }
222 
223  template <typename ArrayType, class Cmp>
224  lint_t partition(ArrayType & a, lint_t l, lint_t r, Cmp & cmp)
225  {
226  int pivot = select_pivot(a, l, r, cmp);
227 
228  std::swap(a[pivot], a[r]);
229 
230  lint_t i = l - 1;
231  lint_t j = r;
232 
233  while (i <= j)
234  {
235  while (cmp(a[++i], a[r]));
236 
237  while (cmp(a[r], a[--j]))
238  if (j == l)
239  break;
240 
241  if (i >= j)
242  break;
243 
244  std::swap(a[i], a[j]);
245  }
246 
247  std::swap(a[i], a[r]);
248 
249  return i;
250  }
251 
252  template <typename ArrayType, class Cmp>
253  void quicksort(ArrayType & a, lint_t l, lint_t r, Cmp & cmp)
254  {
255  if (l >= r)
256  return;
257 
258  if (r - l + 1 <= QuicksortThreshold)
259  {
260  insertion_sort(a, l, r, cmp);
261  return;
262  }
263 
264  lint_t pivot = partition(a, l, r, cmp);
265 
266  if (pivot - l < r - pivot)
267  {
268  quicksort(a, l, pivot - 1, cmp);
269  quicksort(a, pivot + 1, r, cmp);
270  }
271  else
272  {
273  quicksort(a, pivot + 1, r, cmp);
274  quicksort(a, l, pivot - 1, cmp);
275  }
276  }
277 
278  template <class ArrayType,
279  class Cmp = std::less<typename ArrayType::DataType>> inline
280  void quicksort(ArrayType & a, lint_t l, lint_t r, Cmp && cmp = Cmp())
281  {
282  quicksort<ArrayType, Cmp>(a, l, r, cmp);
283  }
284 
285  template <class ArrayType, class Cmp>
286  inline void quicksort(ArrayType & a, lint_t size, Cmp & cmp)
287  {
288  quicksort(a, 0, size - 1, cmp);
289  }
290 
291  template <class ArrayType,
292  class Cmp = std::less<typename ArrayType::DataType>>
293  inline void quicksort(ArrayType & a, lint_t size, Cmp && cmp = Cmp())
294  {
295  quicksort<ArrayType, Cmp>(a, size, cmp);
296  }
297 
298  template <class ArrayType, class Cmp>
299  inline void quicksort(ArrayType & a, Cmp & cmp)
300  {
301  quicksort(a, a.size(), cmp);
302  }
303 
304  template <class ArrayType,
305  class Cmp = std::less<typename ArrayType::DataType>>
306  inline void quicksort(ArrayType & a, Cmp && cmp = Cmp())
307  {
308  quicksort<ArrayType, Cmp>(a, cmp);
309  }
310 
311  template <typename T, class Cmp = std::less<T>>
312  inline void quicksort(FixedArray<T> & a, Cmp & cmp)
313  {
314  quicksort<FixedArray<T>, Cmp>(a, cmp);
315  }
316 
317  template <typename T, class Cmp = std::less<T>>
318  inline void quicksort(FixedArray<T> & a, Cmp && cmp = Cmp())
319  {
320  quicksort<T, Cmp>(a, cmp);
321  }
322 
323  template <typename T, class Cmp = std::less<T>>
324  inline void quicksort(DynArray<T> & a, Cmp & cmp)
325  {
326  quicksort<DynArray<T>, Cmp>(a, cmp);
327  }
328 
329  template <typename T, class Cmp = std::less<T>>
330  inline void quicksort(DynArray<T> & a, Cmp && cmp = Cmp())
331  {
332  quicksort<T, Cmp>(a, cmp);
333  }
334 
335  template <typename T, class Cmp>
336  void sift_up(T * a, nat_t l, nat_t r, Cmp & cmp)
337  {
338  nat_t i = r;
339 
340  nat_t u = i / 2;
341 
342  while (u >= l and cmp(a[i], a[u]))
343  {
344  std::swap(a[i], a[u]);
345  i = u;
346  u = i / 2;
347  }
348  }
349 
350  template <typename T, class Cmp>
351  inline void sift_up(T * a, nat_t l, nat_t r, Cmp && cmp = Cmp())
352  {
353  return sift_up<T, Cmp>(a, l, r, cmp);
354  }
355 
356  template <typename T, class Cmp>
357  void sift_down(T * a, nat_t l, nat_t r, Cmp & cmp)
358  {
359  nat_t i = l;
360 
361  nat_t c = i * 2;
362 
363  while (c <= r)
364  {
365  if (c < r)
366  if (cmp(a[c + 1], a[c]))
367  ++c;
368 
369  if (not cmp(a[c], a[i]))
370  break;
371 
372  std::swap(a[c], a[i]);
373  i = c;
374  c = i * 2;
375  }
376  }
377 
378  template <typename T, class Cmp>
379  inline void sift_down(T * a, nat_t l, nat_t r, Cmp && cmp = Cmp())
380  {
381  return sift_down<T, Cmp>(a, l, r, cmp);
382  }
383 
384  template <typename T, class Cmp>
385  std::tuple<NodeSLList<T>, typename NodeSLList<T>::Node *, NodeSLList<T>>
386  partition(NodeSLList<T> & l, Cmp & cmp)
387  {
388  auto pivot = l.remove_first();
389 
390  NodeSLList<T> ls, gs;
391 
392  while (not l.is_empty())
393  {
394  auto p = l.remove_first();
395 
396  if (cmp(p->get_item(), pivot->get_item()))
397  ls.append(p);
398  else
399  gs.append(p);
400  }
401 
402  return std::make_tuple(std::move(ls), pivot, std::move(gs));
403  }
404 
405  template <typename T, class Cmp>
406  void quicksort(NodeSLList<T> & l, Cmp & cmp)
407  {
408  if (l.is_unitarian_or_empty())
409  return;
410 
411  auto part = partition(l, cmp);
412 
413  quicksort(std::get<0>(part), cmp);
414  quicksort(std::get<2>(part), cmp);
415 
416  l.concat(std::get<0>(part));
417  l.append(std::get<1>(part));
418  l.concat(std::get<2>(part));
419  }
420 
421  template <typename T, class Cmp = std::less<T>>
422  inline void quicksort(NodeSLList<T> & l, Cmp && cmp = Cmp())
423  {
424  quicksort<T, Cmp>(l, cmp);
425  }
426 
427  template <class Cmp>
428  std::tuple<DL, DL *, DL> partition(DL & l, Cmp & cmp)
429  {
430  auto pivot = l.remove_next();
431 
432  DL ls, gs;
433 
434  while (not l.is_empty())
435  {
436  auto p = l.remove_next();
437 
438  if (cmp(p, pivot))
439  ls.insert_prev(p);
440  else
441  gs.insert_prev(p);
442  }
443 
444  return std::make_tuple(std::move(ls), pivot, std::move(gs));
445  }
446 
447  template <class Cmp>
448  void quicksort(DL & l, Cmp & cmp)
449  {
450  if (l.is_unitarian_or_empty())
451  return;
452 
453  auto part = partition(l, cmp);
454 
455  quicksort(std::get<0>(part), cmp);
456  quicksort(std::get<2>(part), cmp);
457 
458  l.concat(std::get<0>(part));
459  l.insert_prev(std::get<1>(part));
460  l.concat(std::get<2>(part));
461  }
462 
463  template <class Cmp>
464  inline void quicksort(DL & l, Cmp && cmp = Cmp())
465  {
466  quicksort<Cmp>(l, cmp);
467  }
468 
469  template <typename T, class Cmp>
470  struct KeyCmp
471  {
472  Cmp & cmp;
473 
474  KeyCmp(Cmp & _cmp)
475  : cmp(_cmp)
476  {
477  // empty
478  }
479 
480  KeyCmp(Cmp && _cmp = Cmp())
481  : cmp(_cmp)
482  {
483  // empty
484  }
485 
486  bool operator () (DL * l, DL * r) const
487  {
488  return cmp(static_cast<DLNode<T> *>(l)->get_item(),
489  static_cast<DLNode<T> *>(r)->get_item());
490  }
491  };
492 
493  template <typename T, class Cmp>
494  struct PtrCmp
495  {
496  Cmp & cmp;
497 
498  PtrCmp(Cmp & _cmp)
499  : cmp(_cmp)
500  {
501  // empty
502  }
503 
504  PtrCmp(Cmp && _cmp = Cmp())
505  : cmp(_cmp)
506  {
507  // empty
508  }
509 
510  bool operator () (const T & a, const T & b) const
511  {
512  return cmp(const_cast<T *>(&a), const_cast<T *>(&b));
513  }
514  };
515 
516  template <typename T, class Cmp>
517  inline void quicksort(DLNode<T> & l, Cmp & cmp)
518  {
519  KeyCmp<T, Cmp> key_cmp(cmp);
520  quicksort<KeyCmp<T, Cmp>>(l, key_cmp);
521  }
522 
523  template <typename T, class Cmp = std::less<T>>
524  inline void quicksort(DLNode<T> & l, Cmp && cmp = Cmp())
525  {
526  quicksort<T, Cmp>(l, cmp);
527  }
528 
529  template <typename T, class Cmp>
530  inline void quicksort(DLList<T> & l, Cmp & cmp)
531  {
532  KeyCmp<T, Cmp> key_cmp(cmp);
533  quicksort<KeyCmp<T, Cmp>>(l, key_cmp);
534  }
535 
536  template <typename T, class Cmp = std::less<T>>
537  inline void quicksort(DLList<T> & l, Cmp && cmp = Cmp())
538  {
539  quicksort<T, Cmp>(l, cmp);
540  }
541 
542  template <typename SeqType, class Cmp = std::less<typename SeqType::ItemType>>
543  inline SeqType sort(const SeqType & s, Cmp & cmp)
544  {
545  SeqType ret_val = s;
546  quicksort<typename SeqType::ItemType, Cmp>(ret_val, cmp);
547  return ret_val;
548  }
549 
550  template <typename SeqType, class Cmp = std::less<typename SeqType::ItemType>>
551  inline SeqType sort(const SeqType & s, Cmp && cmp = Cmp())
552  {
553  return sort<SeqType, Cmp>(s, cmp);
554  }
555 
556  template <typename SeqType, class Cmp = std::less<typename SeqType::ItemType>>
557  inline void inline_sort(SeqType & s, Cmp & cmp)
558  {
559  quicksort<typename SeqType::ItemType, Cmp>(s, cmp);
560  }
561 
562  template <typename SeqType, class Cmp = std::less<typename SeqType::ItemType>>
563  inline void inline_sort(SeqType & s, Cmp && cmp = Cmp())
564  {
565  inline_sort<SeqType, Cmp>(s, cmp);
566  }
567 
568  template <class ArrayType>
569  ArrayType reverse(const ArrayType & a)
570  {
571  ArrayType ret_val;
572 
573  for (nat_t i = a.size(); i > 0; --i)
574  ret_val.append(a[i - 1]);
575 
576  return ret_val;
577  }
578 
579  template <class SRCL, class TGTL>
580  TGTL reverse(const SRCL & l)
581  {
582  TGTL ret_val;
583 
584  for (auto item : l)
585  ret_val.insert(item);
586 
587  return ret_val;
588  }
589 
590  template <typename T>
592  {
593  return reverse<FixedArray<T>>(a);
594  }
595 
596  template <typename T>
597  inline DynArray<T> reverse(const DynArray<T> & a)
598  {
599  return reverse<DynArray<T>>(a);
600  }
601 
602  template <typename T>
603  inline SLList<T> reverse(const SLList<T> & l)
604  {
605  return reverse<SLList<T>, SLList<T>>(l);
606  }
607 
608  template <typename T>
609  inline DLList<T> reverse(const DLList<T> & l)
610  {
611  return reverse<DLList<T>, DLList<T>>(l);
612  }
613 
614 } // end namespace Designar
615 
616 # endif // DSGSORT_H
Cmp & cmp
Definition: sort.H:472
constexpr lint_t QuicksortThreshold
Definition: types.H:58
void quicksort(ArrayType &, lint_t, lint_t, Cmp &)
Definition: sort.H:253
void insertion_sort(ArrayType &, lint_t, lint_t, Cmp &)
Definition: sort.H:163
ArrayType reverse(const ArrayType &)
Definition: sort.H:569
Definition: list.H:35
PtrCmp(Cmp &&_cmp=Cmp())
Definition: sort.H:504
bool operator()(DL *l, DL *r) const
Definition: sort.H:486
bool is_empty() const
Definition: nodesdef.H:153
Definition: nodesdef.H:113
Definition: sort.H:470
Definition: sort.H:494
void concat(NodeSLList *l)
Definition: list.H:152
void inline_sort(SeqType &s, Cmp &cmp)
Definition: sort.H:557
bool is_empty() const
Definition: list.H:80
PtrCmp(Cmp &_cmp)
Definition: sort.H:498
lint_t sequential_search(const ArrayType< T > &, const T &, lint_t, lint_t, Cmp &)
Definition: sort.H:125
bool is_unitarian_or_empty() const
Definition: nodesdef.H:158
Definition: list.H:603
KeyCmp(Cmp &&_cmp=Cmp())
Definition: sort.H:480
void append(Node *node)
Definition: list.H:106
Definition: array.H:375
long long lint_t
Definition: types.H:49
Definition: italgorithms.H:33
lint_t select_pivot(ArrayType &a, lint_t l, lint_t r, Cmp &cmp)
Definition: sort.H:212
Definition: nodesdef.H:415
void sift_up(T *, nat_t, nat_t, Cmp &)
Definition: sort.H:336
SLNode< T > Node
Definition: list.H:38
DL * remove_next()
Definition: nodesdef.H:215
Definition: array.H:182
bool is_unitarian_or_empty() const
Definition: list.H:85
Cmp & cmp
Definition: sort.H:496
Definition: array.H:32
void sift_down(T *, nat_t, nat_t, Cmp &)
Definition: sort.H:357
unsigned long int nat_t
Definition: types.H:50
SeqType sort(const SeqType &s, Cmp &cmp)
Definition: sort.H:543
lint_t partition(ArrayType &, lint_t, lint_t, Cmp &)
Definition: sort.H:224
lint_t binary_search(const ArrayType< T > &, const T &, lint_t, lint_t, Cmp &)
Definition: sort.H:81
void concat(DL *l)
Definition: nodesdef.H:263
KeyCmp(Cmp &_cmp)
Definition: sort.H:474
Node * remove_first()
Definition: list.H:137
void insert_prev(DL *node)
Definition: nodesdef.H:198