1 |
786 |
skrzyp |
// This file is part of the uSTL library, an STL implementation.
|
2 |
|
|
//
|
3 |
|
|
// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net>
|
4 |
|
|
// This file is free software, distributed under the MIT License.
|
5 |
|
|
|
6 |
|
|
#ifndef UHEAP_H_574B9EAF271A1C107190B4D575A356C5
|
7 |
|
|
#define UHEAP_H_574B9EAF271A1C107190B4D575A356C5
|
8 |
|
|
|
9 |
|
|
#include "ualgobase.h"
|
10 |
|
|
|
11 |
|
|
namespace ustl {
|
12 |
|
|
|
13 |
|
|
/// \brief Returns true if the given range is a heap under \p comp.
|
14 |
|
|
/// A heap is a sequentially encoded binary tree where for every node
|
15 |
|
|
/// comp(node,child1) is false and comp(node,child2) is false.
|
16 |
|
|
/// \ingroup HeapAlgorithms
|
17 |
|
|
/// \ingroup ConditionAlgorithms
|
18 |
|
|
///
|
19 |
|
|
template <typename RandomAccessIterator, typename Compare>
|
20 |
|
|
bool is_heap (RandomAccessIterator first, RandomAccessIterator last, Compare comp)
|
21 |
|
|
{
|
22 |
|
|
RandomAccessIterator iChild (first);
|
23 |
|
|
for (; ++iChild < last; ++first)
|
24 |
|
|
if (comp (*first, *iChild) || (++iChild < last && comp (*first, *iChild)))
|
25 |
|
|
return (false);
|
26 |
|
|
return (true);
|
27 |
|
|
}
|
28 |
|
|
|
29 |
|
|
/// \brief make_heap turns the range [first, last) into a heap
|
30 |
|
|
/// At completion, is_heap (first, last, comp) is true.
|
31 |
|
|
/// The algorithm is adapted from "Classic Data Structures in C++" by Timothy Budd.
|
32 |
|
|
/// \ingroup HeapAlgorithms
|
33 |
|
|
/// \ingroup SortingAlgorithms
|
34 |
|
|
///
|
35 |
|
|
template <typename RandomAccessIterator, typename Compare>
|
36 |
|
|
void make_heap (RandomAccessIterator first, RandomAccessIterator last, Compare comp)
|
37 |
|
|
{
|
38 |
|
|
typedef typename iterator_traits<RandomAccessIterator>::value_type value_type;
|
39 |
|
|
const value_type v (*first);
|
40 |
|
|
uoff_t iChild, iHole = 0, iEnd (distance (first, last));
|
41 |
|
|
while ((iChild = 2 * iHole + 1) < iEnd) {
|
42 |
|
|
if (iChild + 1 < iEnd) // Pick the greater child
|
43 |
|
|
iChild += comp (first[iChild], first[iChild + 1]);
|
44 |
|
|
if (comp (first[iChild], v))
|
45 |
|
|
break; // Done when parent is greater than both children.
|
46 |
|
|
first[iHole] = first[iChild];
|
47 |
|
|
iHole = iChild;
|
48 |
|
|
}
|
49 |
|
|
if (iHole < iEnd)
|
50 |
|
|
first[iHole] = v;
|
51 |
|
|
}
|
52 |
|
|
|
53 |
|
|
/// \brief Inserts the *--last into the preceeding range assumed to be a heap.
|
54 |
|
|
/// \ingroup HeapAlgorithms
|
55 |
|
|
/// \ingroup MutatingAlgorithms
|
56 |
|
|
template <typename RandomAccessIterator, typename Compare>
|
57 |
|
|
void push_heap (RandomAccessIterator first, RandomAccessIterator last, Compare comp)
|
58 |
|
|
{
|
59 |
|
|
if (last <= first)
|
60 |
|
|
return;
|
61 |
|
|
typedef typename iterator_traits<RandomAccessIterator>::value_type value_type;
|
62 |
|
|
const value_type v (*--last);
|
63 |
|
|
while (first < last) {
|
64 |
|
|
RandomAccessIterator iParent = first + (distance(first, last) - 1) / 2;
|
65 |
|
|
if (comp (v, *iParent))
|
66 |
|
|
break;
|
67 |
|
|
*last = *iParent;
|
68 |
|
|
last = iParent;
|
69 |
|
|
}
|
70 |
|
|
*last = v;
|
71 |
|
|
}
|
72 |
|
|
|
73 |
|
|
/// Removes the largest element from the heap (*first) and places it at *(last-1)
|
74 |
|
|
/// [first, last-1) is a heap after this operation.
|
75 |
|
|
/// \ingroup HeapAlgorithms
|
76 |
|
|
/// \ingroup MutatingAlgorithms
|
77 |
|
|
template <typename RandomAccessIterator, typename Compare>
|
78 |
|
|
void pop_heap (RandomAccessIterator first, RandomAccessIterator last, Compare comp)
|
79 |
|
|
{
|
80 |
|
|
if (--last <= first)
|
81 |
|
|
return;
|
82 |
|
|
iter_swap (first, last);
|
83 |
|
|
make_heap (first, last, comp);
|
84 |
|
|
}
|
85 |
|
|
|
86 |
|
|
/// Sorts heap [first, last) in descending order according to comp.
|
87 |
|
|
/// \ingroup HeapAlgorithms
|
88 |
|
|
/// \ingroup SortingAlgorithms
|
89 |
|
|
template <typename RandomAccessIterator, typename Compare>
|
90 |
|
|
void sort_heap (RandomAccessIterator first, RandomAccessIterator last, Compare comp)
|
91 |
|
|
{
|
92 |
|
|
for (; first < last; --last)
|
93 |
|
|
pop_heap (first, last, comp);
|
94 |
|
|
}
|
95 |
|
|
|
96 |
|
|
#define HEAP_FN_WITH_LESS(rtype, name) \
|
97 |
|
|
template <typename RandomAccessIterator>\
|
98 |
|
|
inline rtype name (RandomAccessIterator first, RandomAccessIterator last) \
|
99 |
|
|
{ \
|
100 |
|
|
typedef typename iterator_traits<RandomAccessIterator>::value_type value_type; \
|
101 |
|
|
return (name (first, last, less<value_type>())); \
|
102 |
|
|
}
|
103 |
|
|
HEAP_FN_WITH_LESS (bool, is_heap)
|
104 |
|
|
HEAP_FN_WITH_LESS (void, make_heap)
|
105 |
|
|
HEAP_FN_WITH_LESS (void, push_heap)
|
106 |
|
|
HEAP_FN_WITH_LESS (void, pop_heap)
|
107 |
|
|
HEAP_FN_WITH_LESS (void, sort_heap)
|
108 |
|
|
#undef HEAP_FN_WITH_LESS
|
109 |
|
|
|
110 |
|
|
/// \class priority_queue uheap.h ustl.h
|
111 |
|
|
/// \ingroup Sequences
|
112 |
|
|
///
|
113 |
|
|
/// \brief Sorted queue adapter to uSTL containers.
|
114 |
|
|
///
|
115 |
|
|
/// Acts just like the queue adapter, but keeps the elements sorted by priority
|
116 |
|
|
/// specified by the given comparison operator.
|
117 |
|
|
///
|
118 |
|
|
template <typename T, typename Ctr = vector<T>, typename Comp = less<typename Ctr::value_type> >
|
119 |
|
|
class priority_queue {
|
120 |
|
|
public:
|
121 |
|
|
typedef Ctr base_ctr;
|
122 |
|
|
typedef typename base_ctr::value_type value_type;
|
123 |
|
|
typedef typename base_ctr::size_type size_type;
|
124 |
|
|
typedef typename base_ctr::const_pointer const_pointer;
|
125 |
|
|
typedef typename base_ctr::const_reference reference;
|
126 |
|
|
public:
|
127 |
|
|
priority_queue (const Comp& c = Comp()) : m_v(), m_c (c) {}
|
128 |
|
|
priority_queue (const_pointer f, const_pointer l, const Comp& c = Comp())
|
129 |
|
|
: m_v (f, l), m_c (c) { make_heap (m_v.begin(), m_v.end(), m_c); }
|
130 |
|
|
inline size_type size (void) const { return (m_v.size()); }
|
131 |
|
|
inline bool empty (void) const { return (m_v.empty()); }
|
132 |
|
|
inline reference top (void) const { return (m_v.at(0)); }
|
133 |
|
|
inline void push (reference v) { m_v.push_back (v); make_heap (m_v.begin(), m_v.end(), m_c); }
|
134 |
|
|
inline void pop (void) { pop_heap (m_v.begin(), m_v.end()); m_v.pop_back(); }
|
135 |
|
|
private:
|
136 |
|
|
base_ctr m_v; ///< Element container.
|
137 |
|
|
Comp m_c; ///< Comparison functor by value.
|
138 |
|
|
};
|
139 |
|
|
|
140 |
|
|
} // namespace ustl
|
141 |
|
|
|
142 |
|
|
#endif
|