defautl version调用有user-defined compare functor的版本,并指定为std::less<>{}
std::adddress(std::declval<Tp>()) 作为param用于传递元信息(meta info)
仿照的是老式的泛型algorithm的实现(C ++ 11 左右),封装性低(没有iterator_traits,concepts & requires, decltype(auto)的适用等等),所以便于底层的impl insight的查看
template <typename RandomAccessIterator, typename Compare>
constexpr void partial_sort(
RandomAccessIterator first,
RandomAccessIterator middle,
RandomAccessIterator last,
Compare comp){
__partial_sort(first, middle, last,
std::addressof(typename std::iterator_traits<RandomAccessIterator>::value_type {})
std::addressof(typename std::iterator_traits<RandomAccessIterator>::difference_type{}),
std::addressof(comp));
}
template <typename RandomAccessIterator>
constexpr void partial_sort(
RandomAccessIterator first,
RandomAccessIterator middle,
RandomAccessIterator last){
return (void)(partial_sort(first, middle, last, std::less<>()));
}
auxiliary function【__partial_sort function】的impl insight:
首先将range:[first, middle)之间的容器slice整理成max-heap
然后遍历range:[middle, last),在后面搜索比* first更小的元素,置为更合适的heap-top,然后shift-down(调用adjust_heap, 实质上为shift-down + push_heap), 然后调整range:[first, middle]再次成为max-heap
最终将整个容器中top-k构成的元素集合在range:[first, middle)中构成的max-heap进行排序(调用pop_heap)
template <typename RandomAccessIterator, typename Tp, typename Distance, typename Compare>
void __partial_sort(
RandomAccessIterator first,
RandomAccessIterator middle,
RandomAccessIterator last,
Tp * const,
Distance * const,
Compare * const,
Tp * const){
make_heap(first, middle, std::addressof(Compare{}));
auto it { middle };
while(!(it == last)){
if(std::declval<Compare>()(*it, *first))
__pop_heap(first, middle, it,
Tp {*it},
std::addressof(typename std::iterator_traits<RandomAccessIterator>::differenc_type {}),
std::addressof(std::declval<Compare>()));
it ++;
}
sort_heap(first, last,
std::addressof(Tp{}),
std::addressof(Distance {}),
std::addressof(std::declval<Compare>()));
}
make_heap从leaf-nodes的编号最后一个开始检查并调整,迭代地调整整个tree-like array(原容器的range:[first, middle)区间 ),直到第一个元素,此时容器切片被调整为一个天然的max-heap
template <typename RandomAccessIterator, typename Tp, typename Distance, typename Compare>
void __make_heap(
RandomAccessIterator first,
RandomAccessIterator last,
Tp * const,
Distance * const,
Compare * const){
Distance length { std::distance(first, last) };
if(length < Distance {2U}) return;
Distance parent { (length - 2) / 2 };
do{
__adjuct_heap(first, parent, length, Tp {*(first + parent)}, std::addressof(std::declval<Compare>()));
parent --;
}while(!(parent == Distance {0U}));
}
template <typename RandomAccessIterator, typename Tp, typename Distance, typename Compare>
constexpr void make_heap(
RandomAccessIterator first,
RandomAccessIterator last,
Tp * const,
Distance * const,
Compare * const){
__make_heap(first, last, std::addressof(Tp {}), std::addressof(Distance {}));
}
pop_heap 将* result赋值成* first(该max-heap的top), 并将此时的first position视作hole position进行逻辑删除,通过adjust_heap上浮调整失衡的堆
template <typename RandomAccessIterator, typename Tp, typename Distance, typename Compare>
constexpr void __pop_heap(
RandomAccessIterator first,
RandomAccessIterator last,
RandomAccessIterator result,
Tp && value,
Distance * const,
Compare * const){
(void) std::exchange(*result, *first);
__adjuct_heap(first, Distance {0U}, std::distance(first, last),
std::forward<Tp>(value),
std::addressof(std::declval<Compare>()));
}
adjust_heap通过double-pointer的方法,沿着minimal-oriented路径,将堆上浮,调整原先heap的hole position,最终将给定的value填补到最后一个位置上,注意special-judge: second_child == length, 需要判断最后一个节点没有右子树的情况
template <typename RandomAccessIterator, typename Tp, typename Distance, typename Compare>
void __adjuct_heap(
RandomAccessIterator first,
Distance hole,
Distance length,
Tp && value,
Compare * const){
Distance top { hole };
Distance second_child { 2U * hole + 2U };
while(second_child < length){
if(std::declval<Compare>()(*(first + second_child), *std::prev(first + second_child)))
second_child --;
(void) std::exchange(*(first + hole), *(first + second_child));
hole = second_child;
second_child = 2U * second_child + 2U;
}
if(second_child == length){
(void) std::exchange(*(first + hole), *std::prev(first + second_child));
hole = length - 1;
}
__push_heap(first, hole, top, std::forward<Tp>(value));
}
push_heap先自底向上检查和调整max-heap, 最后把value赋值到* first的位置上
template <typename RandomAccessIterator, typename Tp, typename Distance, typename Compare>
void __push_heap(RandomAccessIterator first, Distance hole, Distance top, Tp && value, Compare * const){
Distance parent { (hole - 1)/2 };
while(hole > top && std::declval<Compare>()(*(first + parent), value)){
(void) std::exchange(*(first + hole), *(first + parent));
hole = parent;
parent = (hole - 1U)/2U;
}
(void) std::exchange(*(first + hole), std::forward<Tp>(value));
}
sort_heap的实现思路很想random_shuffle,将max-node 置为最后一个,同时更新last,调整堆的大小,最终实现原线性空间自然有序
template <typename RandomAccessIterator, typename Tp, typename Distance, typename Compare>
void sort_heap(RandomAccessIterator first, RandomAccessIterator last, Tp * const, Distance * const, Compare * const){
while(std::distance(first, last) > Distance { 1U }){
__pop_heap(first, last, std::prev(last), *last, std::addressof(Tp {}), std::addressof(Distance {}));
std::advance(last, -1);
}
}