gctf2023/pwn/flipper/dist/common/include/ustl/uheap.h
2023-11-24 13:11:34 -05:00

162 lines
6.3 KiB
C++

// This file is part of the uSTL library, an STL implementation.
//
// Copyright (c) 2005 by Mike Sharov <msharov@users.sourceforge.net>
// This file is free software, distributed under the MIT License.
#pragma once
#include "ualgobase.h"
namespace ustl {
/// \brief Returns true if the given range is a heap under \p comp.
/// A heap is a sequentially encoded binary tree where for every node
/// comp(node,child1) is false and comp(node,child2) is false.
/// \ingroup HeapAlgorithms
/// \ingroup ConditionAlgorithms
///
template <typename RandomAccessIterator, typename Compare>
bool is_heap (RandomAccessIterator first, RandomAccessIterator last, Compare comp)
{
RandomAccessIterator iChild (first);
for (; ++iChild < last; ++first)
if (comp (*first, *iChild) || (++iChild < last && comp (*first, *iChild)))
return false;
return true;
}
/// Utility function to "trickle down" the root item - swaps the root item with its
/// largest child and recursively fixes the proper subtree.
template <typename RandomAccessIterator, typename Compare>
void trickle_down_heap (RandomAccessIterator first, size_t iHole, size_t heapSize, Compare comp)
{
typedef typename iterator_traits<RandomAccessIterator>::value_type value_type;
const value_type v (first[iHole]);
for (size_t iChild; (iChild = 2 * iHole + 1) < heapSize;) {
if (iChild + 1 < heapSize)
iChild += comp (first[iChild], first[iChild + 1]);
if (comp (v, first[iChild])) {
first[iHole] = first[iChild];
iHole = iChild;
} else
break;
}
first[iHole] = v;
}
/// \brief make_heap turns the range [first, last) into a heap
/// At completion, is_heap (first, last, comp) is true.
/// The algorithm is adapted from "Classic Data Structures in C++" by Timothy Budd.
/// \ingroup HeapAlgorithms
/// \ingroup SortingAlgorithms
///
template <typename RandomAccessIterator, typename Compare>
void make_heap (RandomAccessIterator first, RandomAccessIterator last, Compare comp)
{
if (last <= first)
return;
const size_t heapSize = distance (first, last);
for (RandomAccessIterator i = first + (heapSize - 1)/2; i >= first; --i)
trickle_down_heap (first, distance(first,i), heapSize, comp);
}
/// \brief Inserts the *--last into the preceeding range assumed to be a heap.
/// \ingroup HeapAlgorithms
/// \ingroup MutatingAlgorithms
template <typename RandomAccessIterator, typename Compare>
void push_heap (RandomAccessIterator first, RandomAccessIterator last, Compare comp)
{
if (last <= first)
return;
typedef typename iterator_traits<RandomAccessIterator>::value_type value_type;
const value_type v (*--last);
while (first < last) {
RandomAccessIterator iParent = first + (distance(first, last) - 1) / 2;
if (comp (v, *iParent))
break;
*last = *iParent;
last = iParent;
}
*last = v;
}
/// Removes the largest element from the heap (*first) and places it at *(last-1)
/// [first, last-1) is a heap after this operation.
/// \ingroup HeapAlgorithms
/// \ingroup MutatingAlgorithms
template <typename RandomAccessIterator, typename Compare>
void pop_heap (RandomAccessIterator first, RandomAccessIterator last, Compare comp)
{
if (--last <= first)
return;
iter_swap (first, last);
trickle_down_heap (first, 0, distance(first,last), comp);
}
/// Sorts heap [first, last) in descending order according to comp.
/// \ingroup HeapAlgorithms
/// \ingroup SortingAlgorithms
template <typename RandomAccessIterator, typename Compare>
void sort_heap (RandomAccessIterator first, RandomAccessIterator last, Compare comp)
{
for (; first < last; --last)
pop_heap (first, last, comp);
}
#define HEAP_FN_WITH_LESS(rtype, name) \
template <typename RandomAccessIterator>\
inline rtype name (RandomAccessIterator first, RandomAccessIterator last) \
{ \
typedef typename iterator_traits<RandomAccessIterator>::value_type value_type; \
return name (first, last, less<value_type>()); \
}
HEAP_FN_WITH_LESS (bool, is_heap)
HEAP_FN_WITH_LESS (void, make_heap)
HEAP_FN_WITH_LESS (void, push_heap)
HEAP_FN_WITH_LESS (void, pop_heap)
HEAP_FN_WITH_LESS (void, sort_heap)
#undef HEAP_FN_WITH_LESS
/// \class priority_queue uheap.h ustl.h
/// \ingroup Sequences
///
/// \brief Sorted queue adapter to uSTL containers.
///
/// Acts just like the queue adapter, but keeps the elements sorted by priority
/// specified by the given comparison operator.
///
template <typename T, typename Container = vector<T>, typename Comp = less<typename Container::value_type> >
class priority_queue {
public:
typedef Container container_type;
typedef typename container_type::size_type size_type;
typedef typename container_type::value_type value_type;
typedef typename container_type::reference reference;
typedef typename container_type::const_reference const_reference;
typedef typename container_type::const_iterator const_iterator;
public:
inline explicit priority_queue (const Comp& c = Comp()) : _v(), _c(c) {}
inline priority_queue (const Comp& c, const container_type& v) : _v(v), _c(c) {}
priority_queue (const_iterator f, const_iterator l, const Comp& c = Comp())
: _v(f, l), _c(c) { make_heap (_v.begin(), _v.end(), _c); }
inline size_type size (void) const { return _v.size(); }
inline bool empty (void) const { return _v.empty(); }
inline const_reference top (void) const { return _v.front(); }
inline void push (const_reference v){ _v.push_back (v); push_heap (_v.begin(), _v.end(), _c); }
inline void pop (void) { pop_heap (_v.begin(), _v.end()); _v.pop_back(); }
inline void swap (priority_queue& v){ _v.swap (v._v); swap (_c, v._c); }
#if HAVE_CPP11
inline explicit priority_queue (priority_queue&& v) : _v(move(v._v)),_c(v._c) {}
inline priority_queue (const Comp& c, container_type&& v) : _v(move(v)),_c(c) {}
priority_queue (const_iterator f, const_iterator l, const Comp& c, container_type&& v)
: _v(move(v)), _c(c) { _v.insert (_v.end(), f, l); make_heap (_v.begin(), _v.end(), _c); }
inline priority_queue& operator= (priority_queue&& v) { swap (v); return *this; }
template <typename... Args>
inline void emplace (Args&&... args) { _v.emplace_back (forward<Args>(args)...); push_heap (_v.begin(), _v.end(), _c); }
#endif
private:
container_type _v; ///< Element container.
Comp _c; ///< Comparison functor by value.
};
} // namespace ustl