Skip to content

Commit d1c84fd

Browse files
committed
Add a fast replace_top method to std::priority_queue.
Also `std::poke_heap(first, last)`, which assumes that the given range is in max-heap order *except* for the first element, which needs to be put into its proper place. This is just like `push_heap`, except that `push_heap` assumes the *last* element is out of order, whereas `poke_heap` assumes the *first* element is out of order. The changes in `<queue>` could use `_VSTD::poke_heap` instead of `__sift_down`, but they do not, in order to keep the `<queue>` changes usable as a single-file patch (in case someone wants to take the `<queue>` changes without the `<algorithm>` changes). The `poke_heap` approach would replace the last line of each new method with this line instead: _VSTD::poke_heap(c.begin(), c.end(), comp); https://reviews.llvm.org/D57734
1 parent 49af5dc commit d1c84fd

File tree

2 files changed

+68
-0
lines changed

2 files changed

+68
-0
lines changed

include/algorithm

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4907,6 +4907,32 @@ pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
49074907
_VSTD::pop_heap(__first, __last, __less<typename iterator_traits<_RandomAccessIterator>::value_type>());
49084908
}
49094909

4910+
// poke_heap
4911+
4912+
template <class _RandomAccessIterator, class _Compare>
4913+
inline _LIBCPP_INLINE_VISIBILITY
4914+
void
4915+
poke_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp)
4916+
{
4917+
typename iterator_traits<_RandomAccessIterator>::difference_type __len = __last - __first;
4918+
#ifdef _LIBCPP_DEBUG
4919+
typedef typename add_lvalue_reference<__debug_less<_Compare> >::type _Comp_ref;
4920+
__debug_less<_Compare> __c(__comp);
4921+
__sift_down<_Comp_ref>(__first, __last, __comp, __len, __first);
4922+
#else // _LIBCPP_DEBUG
4923+
typedef typename add_lvalue_reference<_Compare>::type _Comp_ref;
4924+
__sift_down<_Comp_ref>(__first, __last, __comp, __len, __first);
4925+
#endif // _LIBCPP_DEBUG
4926+
}
4927+
4928+
template <class _RandomAccessIterator>
4929+
inline _LIBCPP_INLINE_VISIBILITY
4930+
void
4931+
poke_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
4932+
{
4933+
_VSTD::poke_heap(__first, __last, __less<typename iterator_traits<_RandomAccessIterator>::value_type>());
4934+
}
4935+
49104936
// make_heap
49114937

49124938
template <class _Compare, class _RandomAccessIterator>

include/queue

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -544,6 +544,16 @@ public:
544544
_LIBCPP_INLINE_VISIBILITY
545545
void pop();
546546

547+
_LIBCPP_INLINE_VISIBILITY
548+
void replace_top(const value_type& __v);
549+
#ifndef _LIBCPP_CXX03_LANG
550+
_LIBCPP_INLINE_VISIBILITY
551+
void replace_top(value_type&& __v);
552+
template <class... _Args>
553+
_LIBCPP_INLINE_VISIBILITY
554+
void reemplace_top(_Args&&... __args);
555+
#endif // _LIBCPP_CXX03_LANG
556+
547557
_LIBCPP_INLINE_VISIBILITY
548558
void swap(priority_queue& __q)
549559
_NOEXCEPT_(__is_nothrow_swappable<container_type>::value &&
@@ -766,6 +776,38 @@ priority_queue<_Tp, _Container, _Compare>::pop()
766776
c.pop_back();
767777
}
768778

779+
template <class _Tp, class _Container, class _Compare>
780+
inline
781+
void
782+
priority_queue<_Tp, _Container, _Compare>::replace_top(const value_type& __v)
783+
{
784+
c.front() = __v;
785+
__sift_down<typename add_lvalue_reference<_Compare>::type>(c.begin(), c.end(), comp, c.size(), c.begin());
786+
}
787+
788+
#ifndef _LIBCPP_CXX03_LANG
789+
790+
template <class _Tp, class _Container, class _Compare>
791+
inline
792+
void
793+
priority_queue<_Tp, _Container, _Compare>::replace_top(value_type&& __v)
794+
{
795+
c.front() = _VSTD::move(__v);
796+
__sift_down<typename add_lvalue_reference<_Compare>::type>(c.begin(), c.end(), comp, c.size(), c.begin());
797+
}
798+
799+
template <class _Tp, class _Container, class _Compare>
800+
template <class... _Args>
801+
inline
802+
void
803+
priority_queue<_Tp, _Container, _Compare>::reemplace_top(_Args&&... __args)
804+
{
805+
c.front() = _Tp(_VSTD::forward<_Args>(__args)...);
806+
__sift_down<typename add_lvalue_reference<_Compare>::type>(c.begin(), c.end(), comp, c.size(), c.begin());
807+
}
808+
809+
#endif // _LIBCPP_CXX03_LANG
810+
769811
template <class _Tp, class _Container, class _Compare>
770812
inline
771813
void

0 commit comments

Comments
 (0)