1 /* ///////////////////////////////////////////////////////////////////////
7 * Brief: The sort_impl algorithm
10 * Copyright (c) 2008-2020, Waruqi All rights reserved.
11 * //////////////////////////////////////////////////////////////////// */
13 #ifndef EXTL_ALGORITHM_SORT_IMPL_H
14 #define EXTL_ALGORITHM_SORT_IMPL_H
17 * \brief The sort_impl algorithm
20 # error sort_impl.h need be supported by c++.
23 /* ///////////////////////////////////////////////////////////////////////
26 #include "../prefix.h"
28 /* ///////////////////////////////////////////////////////////////////////
32 EXTL_DETAIL_BEGIN_NAMESPACE
35 template<typename_param_k T
>
36 EXTL_INLINE
void swap_impl(T
& lhs
, T
& rhs
)
43 /* ///////////////////////////////////////////////////////////////////////
48 // bubble_sort_impl - using operator < for ascending
49 template<typename_param_k InIt
>
50 EXTL_INLINE
void bubble_sort_impl(InIt first
, InIt last
)
52 EXTL_ITERATOR_MUST_BE_INPUT(InIt
);
53 EXTL_ASSERT(std_distance(first
, last
) >= 0);
56 for (InIt p1
= first
; p1
!= last
; ++p1
)
57 for (p2
= p1
, ++p2
; p2
!= last
; ++p2
)
58 if (*p2
< *p1
) swap_impl(*p1
, *p2
);
60 // bubble_sort_impl - using pred
61 template< typename_param_k InIt
64 EXTL_INLINE
void bubble_sort_impl(InIt first
, InIt last
, Pr pred
)
66 EXTL_ITERATOR_MUST_BE_INPUT(InIt
);
67 EXTL_ASSERT(std_distance(first
, last
) >= 0);
70 for (InIt p1
= first
; p1
!= last
; ++p1
)
71 for (p2
= p1
, ++p2
; p2
!= last
; ++p2
)
72 if (pred(*p2
, *p1
)) swap_impl(*p1
, *p2
);
75 /* ///////////////////////////////////////////////////////////////////////
80 /* insertion_sort_impl - using operator< for ascending
85 * step1: ((5)) 2 6 2 8 6 1
89 * step2: ((2)) (5) 6 2 8 6 1
93 * step3: 2 5 ((6)) 2 8 6 1
97 * step4: 2 ((2)) (5) (6) 8 6 1
101 * step5: 2 2 5 6 ((8)) 6 1
105 * step6: 2 2 5 6 ((6)) (8) 1
109 * step7: ((1)) (2) (2) (5) (6) (6) (8)
112 template<typename_param_k BidIt
>
113 EXTL_INLINE
void insertion_sort_impl(BidIt first
, BidIt last
)
115 EXTL_ITERATOR_MUST_BE_BIDIRECTIONAL(BidIt
);
116 EXTL_ASSERT(std_distance(first
, last
) >= 0);
117 typedef typename_type_k xtl_iterator_traits
<BidIt
>::value_type value_type
;
121 for (BidIt next
= first
; ++next
!= last
; )
123 value_type val
= *next
;
125 // look for hole and move elements[hole, next - 1] => [hole + 1, next]
126 for (BidIt last2
= next
; last2
!= first
&& val
< *--last2
; next
= last2
)
129 *next
= val
; // val => hole
134 // insertion_sort_impl - using pred
135 template< typename_param_k BidIt
136 , typename_param_k Pr
138 EXTL_INLINE
void insertion_sort_impl(BidIt first
, BidIt last
, Pr pred
)
140 EXTL_ITERATOR_MUST_BE_BIDIRECTIONAL(BidIt
);
141 EXTL_ASSERT(std_distance(first
, last
) >= 0);
142 typedef typename_type_k xtl_iterator_traits
<BidIt
>::value_type value_type
;
146 for (BidIt next
= first
; ++next
!= last
; )
148 value_type val
= *next
;
150 // look for hole and move elements[hole, next - 1] => [hole + 1, next]
151 for (BidIt last2
= next
; last2
!= first
&& pred(val
, *--last2
); next
= last2
)
154 *next
= val
; // val => hole
159 /* ///////////////////////////////////////////////////////////////////////
160 * heap_sort(max-heap)
164 // returns \true if the given range is a valid heap - using operator < for ascending
165 template<typename_param_k RanIt
>
166 EXTL_INLINE e_bool_t
is_valid_heap(RanIt first
, RanIt last
)
170 for (RanIt root
= first
; ++first
!= last
; ++root
)
172 if (*root
< *first
) // *root < left child
174 else if (++first
== last
)
176 else if (*root
< *first
) // *root < right child
183 // returns \true if the given range is a valid heap - using pred
184 template< typename_param_k RanIt
185 , typename_param_k Pr
187 EXTL_INLINE e_bool_t
is_valid_heap(RanIt first
, RanIt last
, Pr pred
)
191 for (RanIt root
= first
; ++first
!= last
; ++root
)
193 if (pred(*root
, *first
))
195 else if (++first
== last
)
197 else if (pred(*root
, *first
))
203 /* push_heap_impl - using operator < for ascending
205 * hole: bottom => top
208 * -------------------------
211 * -------------- -------------
216 * 2 (hole) <= 11(val)
219 * -------------------------
222 * -------------- -------------
229 template< typename_param_k RanIt
230 , typename_param_k Diff
231 , typename_param_k Val
233 EXTL_INLINE
void push_heap_impl(RanIt first
, Diff hole
, Diff top
, Val val
)
235 // (hole - 1) / 2: the parent node of the hole
236 // finds the final hole
237 for (Diff i
= (hole
- 1) / 2; hole
> top
&& *(first
+ i
) < val
; i
= (hole
- 1) / 2)
239 // copy value: parent => hole
240 *(first
+ hole
) = *(first
+ i
);
242 // move node: hole => parent
247 *(first
+ hole
) = val
;
250 // push_heap_impl - using pred
251 template< typename_param_k RanIt
252 , typename_param_k Diff
253 , typename_param_k Val
254 , typename_param_k Pr
256 EXTL_INLINE
void push_heap_impl(RanIt first
, Diff hole
, Diff top
, Val val
, Pr pred
)
258 // (hole - 1) / 2: the parent node of the hole
259 // finds the final hole
260 for (Diff i
= (hole
- 1) / 2; hole
> top
&& pred(*(first
+ i
), val
); i
= (hole
- 1) / 2)
262 // copy value: parent => hole
263 *(first
+ hole
) = *(first
+ i
);
265 // move node: hole => parent
270 *(first
+ hole
) = val
;
273 /* adjust_heap_impl - using operator < for ascending
275 * hole: top => bottom
278 * -------------------------
281 * -------------- -------------
290 * -------------------------
293 * -------------- -------------
298 * 2 (larger)4 1(bottom - 1)
302 * -------------------------
305 * -------------- -------------
310 * 2 (hole) 1(bottom - 1)
312 template< typename_param_k RanIt
313 , typename_param_k Diff
314 , typename_param_k Val
316 EXTL_INLINE
void adjust_heap_impl(RanIt first
, Diff hole
, Diff bottom
, Val val
)
321 // 2 * hole + 2: the right child node of hole
322 Diff i
= 2 * hole
+ 2;
324 for (; i
< bottom
; i
= 2 * i
+ 2)
326 // gets the larger child node
327 if (*(first
+ i
) < *(first
+ (i
- 1))) --i
;
329 // larger child => hole
330 *(first
+ hole
) = *(first
+ i
);
332 // move the hole down to it's larger child node
338 // bottom child => hole
339 *(first
+ hole
) = *(first
+ (bottom
- 1));
341 // move hole down to bottom
345 // push val into the hole
346 push_heap_impl(first
, hole
, top
, val
);
349 // adjust_heap_impl - using pred
350 template< typename_param_k RanIt
351 , typename_param_k Diff
352 , typename_param_k Val
353 , typename_param_k Pr
355 EXTL_INLINE
void adjust_heap_impl(RanIt first
, Diff hole
, Diff bottom
, Val val
, Pr pred
)
360 // 2 * hole + 2: the right child node of hole
361 Diff i
= 2 * hole
+ 2;
363 for (; i
< bottom
; i
= 2 * i
+ 2)
365 // gets the larger child node
366 if (pred(*(first
+ i
), *(first
+ (i
- 1)))) --i
;
368 // larger child => hole
369 *(first
+ hole
) = *(first
+ i
);
371 // move the hole down to it's larger child node
377 // bottom child => hole
378 *(first
+ hole
) = *(first
+ (bottom
- 1));
380 // move hole down to bottom
384 // push val into the hole
385 push_heap_impl(first
, hole
, top
, val
, pred
);
388 // error: there are no arguments to `invariance_error' that depend on a template parameter, so a declaration of `invariance_error' must be available
389 /*#ifdef EXTL_COMPILER_IS_GCC
390 class invariance_error;
392 /* pop_heap_impl - using operator < for ascending
394 * pop *first to *dest and reheap
396 * -------------------------
399 * -------------- | -------------
407 template< typename_param_k RanIt
408 , typename_param_k Val
410 EXTL_INLINE
void pop_heap_impl(RanIt first
, RanIt last
, RanIt dest
, Val val
)
412 EXTL_MESSAGE_ASSERT(is_valid_heap(first
, last
), "invalid heap");
413 //EXTL_ASSERT_THROW(is_valid_heap(first, last), invariance_error("invalid heap"));
415 typedef typename_type_k xtl_iterator_traits
<RanIt
>::difference_type difference_type
;
417 adjust_heap_impl(first
, difference_type(0), difference_type(last
- first
), val
);
419 EXTL_MESSAGE_ASSERT(is_valid_heap(first
, last
), "invalid heap");
420 //EXTL_ASSERT_THROW(is_valid_heap(first, last), invariance_error("invalid heap"));
423 // pop_heap_impl - using pred
424 template< typename_param_k RanIt
425 , typename_param_k Val
426 , typename_param_k Pr
428 EXTL_INLINE
void pop_heap_impl(RanIt first
, RanIt last
, RanIt dest
, Val val
, Pr pred
)
430 EXTL_MESSAGE_ASSERT(is_valid_heap(first
, last
, pred
), "invalid heap");
431 //EXTL_ASSERT_THROW(is_valid_heap(first, last, pred), invariance_error("invalid heap"));
433 typedef typename_type_k xtl_iterator_traits
<RanIt
>::difference_type difference_type
;
435 adjust_heap_impl(first
, difference_type(0), difference_type(last
- first
), val
, pred
);
437 EXTL_MESSAGE_ASSERT(is_valid_heap(first
, last
, pred
), "invalid heap");
438 //EXTL_ASSERT_THROW(is_valid_heap(first, last, pred), invariance_error("invalid heap"));
440 /* pop_heap_0_impl - using operator < for ascending
442 * pop the top of heap to *(last - 1) and reheap
444 * ----------------|--------
447 * -------------- | -------------
455 template<typename_param_k RanIt
>
456 EXTL_INLINE
void pop_heap_0_impl(RanIt first
, RanIt last
)
458 typedef typename_type_k xtl_iterator_traits
<RanIt
>::value_type value_type
;
460 if (last
- first
> 1)
461 pop_heap_impl(first
, last
- 1, last
- 1, value_type(*(last
- 1)));
464 // pop_heap_0_impl - using pred
465 template< typename_param_k RanIt
466 , typename_param_k Pr
468 EXTL_INLINE
void pop_heap_0_impl(RanIt first
, RanIt last
, Pr pred
)
470 typedef typename_type_k xtl_iterator_traits
<RanIt
>::value_type value_type
;
472 if (last
- first
> 1)
473 pop_heap_impl(first
, last
- 1, last
- 1, value_type(*(last
- 1)), pred
);
476 /* make_heap_impl: - using operator < for ascending
477 * heap: 16 14 10 8 7 9 3 2 4 1
480 * -------------------------
483 * -------------- -------------
485 * 8 (bottom / 2 - 1)7 9 3
490 template<typename_param_k RanIt
>
491 EXTL_INLINE
void make_heap_impl(RanIt first
, RanIt last
)
493 typedef typename_type_k xtl_iterator_traits
<RanIt
>::difference_type difference_type
;
494 typedef typename_type_k xtl_iterator_traits
<RanIt
>::value_type value_type
;
496 // adjust heap[0, bottom / 2 - 1]
497 // hole = (bottom / 2 - 1) ... 0
498 difference_type bottom
= last
- first
;
499 for (difference_type hole
= bottom
/ 2; hole
> 0; )
501 // reheap top half, bottom to top
503 adjust_heap_impl(first
, hole
, bottom
, value_type(*(first
+ hole
)));
506 EXTL_MESSAGE_ASSERT(is_valid_heap(first
, last
), "invalid heap");
507 //EXTL_ASSERT_THROW(is_valid_heap(first, last), invariance_error("invalid heap"));
509 // make_heap_impl: - using pred
510 template< typename_param_k RanIt
511 , typename_param_k Pr
513 EXTL_INLINE
void make_heap_impl(RanIt first
, RanIt last
, Pr pred
)
515 typedef typename_type_k xtl_iterator_traits
<RanIt
>::difference_type difference_type
;
516 typedef typename_type_k xtl_iterator_traits
<RanIt
>::value_type value_type
;
518 // adjust heap[0, bottom / 2 - 1]
519 // hole = (bottom / 2 - 1) ... 0
520 difference_type bottom
= last
- first
;
521 for (difference_type hole
= bottom
/ 2; hole
> 0; )
523 // reheap top half, bottom to top
525 adjust_heap_impl(first
, hole
, bottom
, value_type(*(first
+ hole
)), pred
);
528 EXTL_MESSAGE_ASSERT(is_valid_heap(first
, last
, pred
), "invalid heap");
529 //EXTL_ASSERT_THROW(is_valid_heap(first, last, pred), invariance_error("invalid heap"));
531 /* heap_sort_impl(max-heap) - using operator < for ascending
536 * -------------------------
539 * -------------- -------------
549 * -------------------------
552 * -------------- -------------
560 * 16(first)--------------------------
561 * ------------------------- |
564 * -------------- ------------- |
569 * 2 8 1(last - 1) <------------------------------
572 * -------------------------
575 * -------------- -------------
584 * -------------------------
587 * -------------- -------------
592 * 2 (hole)(last - 1) 16
597 * -------------------------
600 * -------------- -------------
604 * | | /-----------------------------------------------
605 * 2 (hole)(last - 1) 16
608 * -------------------------
611 * -------------- -------------
618 * pop_heap adjust_heap push_heap ...
632 * result: 1 2 3 4 7 8 9 10 14 16
634 template<typename_param_k RanIt
>
635 EXTL_INLINE
void heap_sort_impl(RanIt first
, RanIt last
)
637 EXTL_ITERATOR_MUST_BE_RANDOM_ACCESS(RanIt
);
638 EXTL_ASSERT(std_distance(first
, last
) >= 0);
640 make_heap_impl(first
, last
);
642 for (; 1 < last
- first
; --last
)
643 pop_heap_0_impl(first
, last
);
645 // heap_sort_impl(max-heap) - using pred
646 template< typename_param_k RanIt
647 , typename_param_k Pr
649 EXTL_INLINE
void heap_sort_impl(RanIt first
, RanIt last
, Pr pred
)
651 EXTL_ITERATOR_MUST_BE_RANDOM_ACCESS(RanIt
);
652 EXTL_ASSERT(std_distance(first
, last
) >= 0);
654 make_heap_impl(first
, last
, pred
);
656 for (; 1 < last
- first
; --last
)
657 pop_heap_0_impl(first
, last
, pred
);
659 // heap_sort_top_n - using operator < for descending
660 template< typename_param_k RanIt
661 , typename_param_k Diff
663 EXTL_INLINE
void heap_sort_top_n_impl(RanIt first
, RanIt last
, Diff n
)
665 EXTL_ITERATOR_MUST_BE_RANDOM_ACCESS(RanIt
);
666 EXTL_ASSERT(std_distance(first
, last
) >= 0);
669 typedef typename_type_k xtl_iterator_traits
<RanIt
>::value_type value_type
;
670 typedef reverse_iterator_base
<RanIt
> reverse_iterator_type
;
671 reverse_iterator_type
rfirst(last
);
672 reverse_iterator_type
rlast(first
);
674 make_heap_impl(rfirst
, rlast
);
676 for (; 1 < rlast
- rfirst
&& n
--; --rlast
)
677 pop_heap_0_impl(rfirst
, rlast
);
680 // heap_sort_top_n - using pred
681 template< typename_param_k RanIt
682 , typename_param_k Diff
683 , typename_param_k Pr
685 EXTL_INLINE
void heap_sort_top_n_impl(RanIt first
, RanIt last
, Diff n
, Pr pred
)
687 EXTL_ITERATOR_MUST_BE_RANDOM_ACCESS(RanIt
);
688 EXTL_ASSERT(std_distance(first
, last
) >= 0);
691 typedef typename_type_k xtl_iterator_traits
<RanIt
>::value_type value_type
;
692 typedef reverse_iterator_base
<RanIt
> reverse_iterator_type
;
693 reverse_iterator_type
rfirst(last
);
694 reverse_iterator_type
rlast(first
);
696 make_heap_impl(rfirst
, rlast
, pred
);
698 for (; 1 < rlast
- rfirst
&& n
--; --rlast
)
699 pop_heap_0_impl(rfirst
, rlast
, pred
);
702 /* ///////////////////////////////////////////////////////////////////////
705 EXTL_DETAIL_END_NAMESPACE
708 /* //////////////////////////////////////////////////////////////////// */
709 #endif /* EXTL_ALGORITHM_SORT_IMPL_H */
710 /* //////////////////////////////////////////////////////////////////// */