-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathheap.hh
173 lines (164 loc) · 5.73 KB
/
heap.hh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
#ifndef DOZERG_HEAP_H_20080102
#define DOZERG_HEAP_H_20080102
/*
STL风格的堆
CHeap
CFixedHeap 固定大小堆
History:
20071006 为CHeap和CFixedHeap增加swap函数
去掉CFixedHeap的less_和equal_成员变量
CFixedHeap::push_unique函数里使用迭代器,而不是下标
//*/
#include <vector>
#include <algorithm> //std::less, std::make_heap, ...
#include <functional> //std::less, std::equal
#include "impl/environment.hh"
NS_SERVER_BEGIN
//CHeap
template<
class T,
class Container = std::vector<T>,
class BinaryPredicate = std::less<T>
>class CHeap
{
typedef CHeap<T, Container, BinaryPredicate> __Myt;
public:
typedef BinaryPredicate less_comp;
typedef Container container_type;
typedef typename container_type::value_type value_type;
typedef typename container_type::size_type size_type;
protected:
typedef typename container_type::reference reference;
typedef typename container_type::const_reference const_reference;
public:
explicit CHeap(less_comp = less_comp()){}
explicit CHeap(const container_type & cont, less_comp = less_comp())
: cont_(cont)
{
std::make_heap(cont_.begin(), cont_.end(), less_comp());
}
template<class InputIterator>
CHeap(InputIterator first, InputIterator last, less_comp = less_comp())
: cont_(first, last)
{
std::make_heap(cont_.begin(), cont_.end(), less_comp());
}
template<class InputIterator>
CHeap(const container_type & cont, InputIterator first, InputIterator last, less_comp = less_comp())
: cont_(cont)
{
cont_.insert(cont_.end(), first, last);
std::make_heap(cont_.begin(), cont_.end(), less_comp());
}
bool empty() const {return cont_.empty();}
size_type size() const {return cont_.size();}
reference top() {return cont_.front();}
const_reference top() const {return cont_.front();}
void push(const_reference value){
cont_.push_back(value);
std::push_heap(cont_.begin(), cont_.end(), less_comp());
}
void pop(){
std::pop_heap(cont_.begin(), cont_.end(), less_comp());
cont_.pop_back();
}
void swap(__Myt & a) throw() {
std::swap(cont_, a.cont_);
}
private:
container_type cont_;
};
//CFixedHeap
template<
class T,
class Container = std::vector<T>,
class BinaryPredicateLess = std::less<T>, //小于比较算符
class BinaryPredicateEqual = std::equal_to<T> //等于比较算符
>class CFixedHeap
{
typedef CFixedHeap<T, Container, BinaryPredicateLess, BinaryPredicateEqual> __Myt;
public:
typedef BinaryPredicateLess less_comp;
typedef BinaryPredicateEqual equal_comp;
typedef Container container_type;
typedef typename container_type::value_type value_type;
typedef typename container_type::size_type size_type;
protected:
typedef typename container_type::reference reference;
typedef typename container_type::const_reference const_reference;
public:
explicit CFixedHeap(size_t max_size = 10, less_comp = less_comp(), equal_comp = equal_comp())
: max_size_(max_size)
{}
CFixedHeap(size_t max_size, const container_type & cont, less_comp = less_comp(), equal_comp = equal_comp())
: max_size_(max_size)
{
fromRange(cont_.begin(), cont_.end(), cont_.size());
}
template<class InputIterator>
CFixedHeap(InputIterator first, InputIterator last, size_t max_size, less_comp = less_comp(), equal_comp = equal_comp())
: max_size_(max_size)
{
fromRange(first, last, 0);
}
bool empty() const {return cont_.empty();}
size_type size() const {return cont_.size();}
size_type max_size() const {return max_size_;}
reference top() {return cont_.front();}
const_reference top() const {return cont_.front();}
void set_max_size(size_t maxsz){max_size_ = maxsz;}
void push(const_reference value){
if(size() < max_size_){
cont_.push_back(value);
std::push_heap(cont_.begin(), cont_.end(), less_comp());
}else if(max_size_ > 0 && less_comp()(value, top())){
top() = value;
std::make_heap(cont_.begin(), cont_.end(), less_comp());
}
}
void pop(){
std::pop_heap(cont_.begin(), cont_.end(), less_comp());
cont_.pop_back();
}
//保证value不重复
void push_unique(const_reference value){
typedef typename container_type::const_iterator __Iter;
equal_comp eq;
__Iter i = cont_.begin();
for(;i != cont_.end() && !eq(value, *i);++i);
if(i != cont_.end())
std::make_heap(cont_.begin(), cont_.end(), less_comp());
else
push(value);
}
void swap(__Myt & a) throw() {
std::swap(max_size_, a.max_size_);
std::swap(cont_, a.cont_);
}
private:
template<class InputIterator>
void fromRange(InputIterator first, InputIterator last, size_t sz){
if(sz && sz <= max_size_){
cont_.assign(first, last);
std::make_heap(cont_.first(), cont_.last(), less_comp());
}else{
for(;first != last;++first)
push(*first);
}
}
//members:
size_t max_size_;
container_type cont_;
};
template<class T, class C, class P>
inline void swap(CHeap<T, C, P> & a, CHeap<T, C, P> & b)
{
a.swap(b);
}
template<class T, class C, class P1, class P2>
inline void swap(CFixedHeap<T, C, P1, P2> & a, CFixedHeap<T, C, P1, P2> & b)
{
a.swap(b);
}
NS_SERVER_END
#endif