Skip to content

Commit 497215e

Browse files
committed
[libc++] Optimize make_heap() and sift_down()
1 parent c7fa3cf commit 497215e

File tree

2 files changed

+22
-19
lines changed

2 files changed

+22
-19
lines changed

libcxx/include/__algorithm/make_heap.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,12 @@ __make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compar
3434
using difference_type = typename iterator_traits<_RandomAccessIterator>::difference_type;
3535
difference_type __n = __last - __first;
3636
if (__n > 1) {
37-
// start from the first parent, there is no need to consider children
38-
for (difference_type __start = (__n - 2) / 2; __start >= 0; --__start) {
37+
difference_type __start = __n / 2;
38+
do {
39+
// start from the first parent, there is no need to consider children
40+
--__start;
3941
std::__sift_down<_AlgPolicy>(__first, __comp_ref, __n, __first + __start);
40-
}
42+
} while (__start != 0);
4143
}
4244
}
4345

libcxx/include/__algorithm/sift_down.h

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -36,18 +36,16 @@ __sift_down(_RandomAccessIterator __first,
3636
typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type;
3737
// left-child of __start is at 2 * __start + 1
3838
// right-child of __start is at 2 * __start + 2
39-
difference_type __child = __start - __first;
40-
41-
if (__len < 2 || (__len - 2) / 2 < __child)
42-
return;
43-
44-
__child = 2 * __child + 1;
39+
difference_type __child = 2 * (__start - __first) + 1;
4540
_RandomAccessIterator __child_i = __first + __child;
4641

47-
if ((__child + 1) < __len && __comp(*__child_i, *(__child_i + difference_type(1)))) {
48-
// right-child exists and is greater than left-child
49-
++__child_i;
50-
++__child;
42+
if ((__child + 1) < __len) {
43+
_RandomAccessIterator __right_child_i = _Ops::next(__child_i);
44+
if (__comp(*__child_i, *__right_child_i)) {
45+
// right-child exists and is greater than left-child
46+
__child_i = __right_child_i;
47+
++__child;
48+
}
5149
}
5250

5351
// check if we are in heap-order
@@ -61,17 +59,20 @@ __sift_down(_RandomAccessIterator __first,
6159
*__start = _Ops::__iter_move(__child_i);
6260
__start = __child_i;
6361

64-
if ((__len - 2) / 2 < __child)
62+
__child = 2 * __child + 1;
63+
if (!(__child < __len))
6564
break;
6665

6766
// recompute the child based off of the updated parent
68-
__child = 2 * __child + 1;
6967
__child_i = __first + __child;
7068

71-
if ((__child + 1) < __len && __comp(*__child_i, *(__child_i + difference_type(1)))) {
72-
// right-child exists and is greater than left-child
73-
++__child_i;
74-
++__child;
69+
if ((__child + 1) < __len) {
70+
_RandomAccessIterator __right_child_i = _Ops::next(__child_i);
71+
if (__comp(*__child_i, *__right_child_i)) {
72+
// right-child exists and is greater than left-child
73+
__child_i = __right_child_i;
74+
++__child;
75+
}
7576
}
7677

7778
// check if we are in heap-order

0 commit comments

Comments
 (0)