1 //===----------------------------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #ifndef _LIBCPP___ALGORITHM_SIFT_DOWN_H
10 #define _LIBCPP___ALGORITHM_SIFT_DOWN_H
12 #include <__algorithm/iterator_operations.h>
15 #include <__iterator/iterator_traits.h>
16 #include <__utility/move.h>
18 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
19 # pragma GCC system_header
23 #include <__undef_macros>
25 _LIBCPP_BEGIN_NAMESPACE_STD
27 template <class _AlgPolicy
, class _Compare
, class _RandomAccessIterator
>
28 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
void
29 __sift_down(_RandomAccessIterator __first
,
31 typename iterator_traits
<_RandomAccessIterator
>::difference_type __len
,
32 _RandomAccessIterator __start
) {
33 using _Ops
= _IterOps
<_AlgPolicy
>;
35 typedef typename iterator_traits
<_RandomAccessIterator
>::difference_type difference_type
;
36 typedef typename iterator_traits
<_RandomAccessIterator
>::value_type value_type
;
37 // left-child of __start is at 2 * __start + 1
38 // right-child of __start is at 2 * __start + 2
39 difference_type __child
= __start
- __first
;
41 if (__len
< 2 || (__len
- 2) / 2 < __child
)
44 __child
= 2 * __child
+ 1;
45 _RandomAccessIterator __child_i
= __first
+ __child
;
47 if ((__child
+ 1) < __len
&& __comp(*__child_i
, *(__child_i
+ difference_type(1)))) {
48 // right-child exists and is greater than left-child
53 // check if we are in heap-order
54 if (__comp(*__child_i
, *__start
))
55 // we are, __start is larger than its largest child
58 value_type
__top(_Ops::__iter_move(__start
));
60 // we are not in heap-order, swap the parent with its largest child
61 *__start
= _Ops::__iter_move(__child_i
);
64 if ((__len
- 2) / 2 < __child
)
67 // recompute the child based off of the updated parent
68 __child
= 2 * __child
+ 1;
69 __child_i
= __first
+ __child
;
71 if ((__child
+ 1) < __len
&& __comp(*__child_i
, *(__child_i
+ difference_type(1)))) {
72 // right-child exists and is greater than left-child
77 // check if we are in heap-order
78 } while (!__comp(*__child_i
, __top
));
79 *__start
= std::move(__top
);
82 template <class _AlgPolicy
, class _Compare
, class _RandomAccessIterator
>
83 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _RandomAccessIterator
__floyd_sift_down(
84 _RandomAccessIterator __first
,
86 typename iterator_traits
<_RandomAccessIterator
>::difference_type __len
) {
87 using difference_type
= typename iterator_traits
<_RandomAccessIterator
>::difference_type
;
88 _LIBCPP_ASSERT_INTERNAL(__len
>= 2, "shouldn't be called unless __len >= 2");
90 _RandomAccessIterator __hole
= __first
;
91 _RandomAccessIterator __child_i
= __first
;
92 difference_type __child
= 0;
95 __child_i
+= difference_type(__child
+ 1);
96 __child
= 2 * __child
+ 1;
98 if ((__child
+ 1) < __len
&& __comp(*__child_i
, *(__child_i
+ difference_type(1)))) {
99 // right-child exists and is greater than left-child
104 // swap __hole with its largest child
105 *__hole
= _IterOps
<_AlgPolicy
>::__iter_move(__child_i
);
108 // if __hole is now a leaf, we're done
109 if (__child
> (__len
- 2) / 2)
114 _LIBCPP_END_NAMESPACE_STD
118 #endif // _LIBCPP___ALGORITHM_SIFT_DOWN_H