Scaffolding  0.1
This program can assemble genome scaffolds using the pairing information in paired-end reads.
low_priority_queue_old2.hpp
1 
2 // we implement a priority queue taking O(n+k) space
3 // where k is the maximum priority & n is the number of elements in the queue
4 // and the following times:
5 // construct: O(k)
6 // insert: O(log k) (average)
7 // erase (by iterator): O(1)
8 // change_priority (by iterator): O(log k)
9 // get_min, get_max: O(1)
10 // pop_min, pop_max: O(1)
11 
12 #ifndef LOW_PRIORITY_QUEUE
13 #define LOW_PRIORITY_QUEUE
14 
15 #include <list>
16 #include <vector>
17 
18 namespace std{
19 
20  template<class Element, class Priority = size_t, class comparator = less<Priority> >
21  class low_priority_queue{
22  public:
23  // public types
24  typedef typename std::pair<Element, Priority> value_type;
25  typedef typename list<value_type>::const_iterator const_iterator;
26 
27  private:
28  // private types
29  typedef typename list<value_type>::iterator iterator;
30  vector<list<value_type> > prio_to_list;
31  Priority min_priority;
32  const comparator* compare;
33  const bool delete_comparator;
34  const char increment;
35  public:
36 
37  // construct an empty low priority queue & check whether we're a min or a max prio queue
38  low_priority_queue(const comparator& _compare):
39  min_priority(SIZE_MAX),
40  compare(&_compare),
41  delete_comparator(false),
42  increment((*compare)(Priority(0),Priority(1)) ? 1 : -1)
43  {}
44 
45  // construct an empty low priority queue & check whether we're a min or a max prio queue
46  low_priority_queue():
47  min_priority(SIZE_MAX),
48  compare(new comparator()),
49  delete_comparator(true),
50  increment((*compare)(Priority(0),Priority(1)) ? 1 : -1)
51  {}
52 
53  // copy construct a low priority queue
54  low_priority_queue(const low_priority_queue<Element, Priority, comparator>& lpq):
55  compare(new comparator(lpq.compare)),
56  delete_comparator(true),
57  increment(lpq.increment)
58  {
59  bool first = true;
60  for(Priority p(0); p < lpq.prio_to_list.size(); ++p){
61  const list<value_type>& vlist = lpq.prio_to_list[p];
62  if(!vlist.empty()){
63  prio_to_list.emplace_back(vlist);
64  if(first || compare(min_priority, p)){
65  min_priority = p;
66  first = false;
67  }// if
68  }// if
69  }// for
70  }
71 
72  ~low_priority_queue(){
73  if(delete_comparator) delete compare;
74  }
75 
76  // return whether the low priority queue is empty
77  const bool empty() const{
78  return prio_to_list.empty();
79  }
80 
81  // insert an element into the low priority queue, returning a const_iterator to the newly inserted item
82  const_iterator insert(const value_type& value){
83  const Priority& prio = value.second;
84 
85  if((*compare)(prio, min_priority) || empty()) min_priority = prio;
86  if(prio >= prio_to_list.size()) prio_to_list.resize(prio + 1);
87  list<value_type>& prio_list = prio_to_list[prio];
88  prio_list.emplace_front(value);
89  DEBUG5(cout << "inserted item of priority "<<prio_list.front().second<<" min_priority is now "<<min_priority<<endl);
90  return prio_list.begin();
91  }
92 
93  private:
94  // return whether the min_priority can be incremented without running out of bounds
95  bool min_priority_can_be_incremented() const{
96  if(increment == 1) return min_priority < prio_to_list.size() - 1; else return min_priority > 0;
97  }
98  public:
99 
100  // erase an element from the low priority queue, returning an iterator to the following item
101  void erase(const const_iterator& it){
102  const Priority& prio = it->second;
103  assert(prio < prio_to_list.size());
104 
105  list<value_type>& vlist = prio_to_list[prio];
106  vlist.erase(it);
107 
108  // update min_priority
109  while( min_priority_can_be_incremented() && prio_to_list[min_priority].empty()) min_priority += increment;
110  // if the update skipped to one of the extremes in the queue and this extreme is empty, then the queue is empty
111  if(prio_to_list[min_priority].empty()){
112  prio_to_list.clear();
113  DEBUG5(cout << "prio queue now empty"<<endl);
114  } else {
115  DEBUG5(cout << "done erasing an item, new min_priority is "<<min_priority<< " and there are "<<prio_to_list[min_priority].size()<<" such items"<<endl);
116  }
117  }
118 
119  // change the priority of an item in the low priority queue
120  void change_priority(const const_iterator& it, const Priority& new_prio){
121  const Priority& old_prio = it->second;
122  assert(old_prio < prio_to_list.size());
123 
124  if(old_prio != new_prio){
125  // resize if needed
126  if(new_prio >= prio_to_list.size())
127  prio_to_list.resize(new_prio + 1);
128 
129  list<value_type>& source_list = prio_to_list[old_prio];
130  list<value_type>& target_list = prio_to_list[new_prio];
131 
132  target_list.splice(target_list.begin(), source_list, it);
133  target_list.front().second = new_prio;
134 
135  // update min_priority
136  if((*compare)(new_prio, min_priority)) min_priority = new_prio;
137  while(prio_to_list[min_priority].empty()) min_priority += increment;
138  }// if
139  DEBUG5(cout << "changed a priority to "<<new_prio<< ", min priority now "<<min_priority<<" & "<<prio_to_list[new_prio].size()<<" items with the new prio"<<endl);
140  }
141 
142  void decrement_priority(const const_iterator& it){
143  change_priority(it, it->second - 1);
144  }
145  void increment_priority(const const_iterator& it){
146  change_priority(it, it->second + 1);
147  }
148 
149  // return the top of the low priority queue - this is an item of minimum priority
150  value_type& top(){
151  assert(!prio_to_list.empty());
152  return prio_to_list[min_priority].front();
153  }
154  // return the top of the low priority queue - this is an item of minimum priority
155  const value_type& top() const{
156  return prio_to_list[min_priority].front();
157  }
158 
159  // remove the top of the low priority queue and return the next top
160  void pop(){
161  assert(!empty());
162  erase(prio_to_list[min_priority].cbegin());
163  }
164  };
165 
166 };
167 
168 #endif
169 
Definition: low_priority_queue.hpp:18