12 #ifndef LOW_PRIORITY_QUEUE
13 #define LOW_PRIORITY_QUEUE
20 template<
class Element,
class Priority =
size_t>
21 class low_priority_queue{
24 typedef typename std::pair<Element, Priority> value_type;
25 typedef typename list<value_type>::const_iterator const_iterator;
29 typedef typename list<value_type>::iterator iterator;
32 list<value_type> _data;
35 vector<iterator> _start_points;
38 Priority max_priority;
48 low_priority_queue(
const low_priority_queue<Element>& lpq):
49 max_priority(lpq.max_priority)
51 _start_points.resize((
size_t)max_priority + 1);
52 Priority next_prio(0);
54 for(
const value_type& value : lpq._data){
55 const Priority& prio = value.second;
56 const iterator it = _data.emplace_back(value);
58 while(prio > next_prio)
59 _start_points[next_prio++] = _data.end();
61 _start_points[next_prio++] = it;
68 void prepare_start_points_to_receive(
const Priority& new_priority){
69 if(new_priority > max_priority){
70 _start_points.resize((
size_t)new_priority + 1);
71 while(new_priority > max_priority)
72 _start_points[++max_priority] = _data.end();
76 void update_start_point_assuming_we_remove(
const iterator& it){
77 const Priority& prio = it->second;
78 iterator& first_element = _start_points[prio];
79 if(first_element == it){
81 iterator next_element = it;
84 if((next_element == _data.end()) || (next_element->second == prio)){
87 first_element = next_element;
90 first_element = _data.end();
96 const_iterator get_insertion_position(
const Priority& prio) {
97 typename vector<iterator>::const_iterator start_point_it(_start_points.cbegin() + prio);
100 while( (start_point_it != _start_points.end()) && (*start_point_it == _data.end()))
103 if(start_point_it == _start_points.end()) {
106 }
else return *start_point_it;
111 const_iterator insert(
const value_type& value){
112 DEBUG5(cout <<
"inserting degree "<<value.second<<
" (max is "<<max_priority<<
")"<<endl);
113 const Priority& prio = value.second;
115 prepare_start_points_to_receive(prio);
116 DEBUG5(cout <<
"prepared for insertion, max is now "<<max_priority<<endl);
118 const iterator& it = _data.emplace(get_insertion_position(prio), value);
119 iterator& i = _start_points[prio];
120 if(i == _data.end()) i = it;
122 DEBUG5(cout <<
"done inserting "<< it->second<<
"; the first degree is now "<<_data.front().second<<endl);
127 iterator erase(
const const_iterator& it){
128 assert(it != _data.end());
129 const value_type& value = *it;
130 const Priority& prio = value.second;
131 assert(prio <= max_priority);
134 update_start_point_assuming_we_remove(it);
137 return _data.erase(it);
141 void decrement_priority(
const const_iterator& it){
142 assert(it != _data.end());
143 const Priority old_prio = it->second;
144 assert(old_prio <= max_priority);
145 assert(old_prio > 0);
148 const iterator mutable_it = _data.erase(it, it);
151 Priority& new_prio(mutable_it->second);
153 iterator& new_start_point = _start_points[new_prio];
156 iterator& start_element = _start_points[old_prio];
157 assert(start_element != _data.end());
160 iterator where_inserted;
161 if(start_element == it){
162 iterator next_element = std::next(start_element);
164 if(next_element == _data.end()){
166 start_element = _data.end();
169 if(next_element->second == old_prio)
170 start_element = _data.end();
172 start_element = next_element;
174 where_inserted = next_element;
178 _data.splice(start_element, _data, it);
179 where_inserted = start_element;
184 if(new_start_point == _data.end())
185 new_start_point = std::prev(where_inserted);
187 DEBUG5(cout <<
"done decreasing prio from "<<old_prio<<
" to "<<new_prio<<endl);
188 DEBUG5(
if(_start_points[old_prio] == _data.end()) cout <<
"start["<<old_prio<<
"] is now void"<<endl);
189 DEBUG5(
if(_start_points[new_prio] == _data.end()) cout <<
"start["<<new_prio<<
"] is now void"<<endl);
194 void change_priority(
const const_iterator& it,
const Priority& new_priority){
195 assert(it != _data.end());
196 const value_type& value = *it;
197 const Priority& prio = value.second;
198 assert(prio <= max_priority);
200 if(prio != new_priority){
202 update_prio_pointer_assuming_we_remove(it);
204 prepare_start_points_to_receive(prio);
206 const const_iterator insert_here = get_insertion_position(prio);
208 _data.splice(insert_here, _data, it);
210 _start_points[prio] = std::prev(insert_here);
216 return _data.empty();
221 return _data.front();
224 const value_type& top()
const{
225 return _data.front();
229 const_iterator pop(){
232 update_start_point_assuming_we_remove(_data.begin());
235 return _data.erase(_data.begin());
Definition: low_priority_queue.hpp:18