Scippy

SCIP

Solving Constraint Integer Programs

pqueue.h
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program and library */
4 /* SCIP --- Solving Constraint Integer Programs */
5 /* */
6 /* Copyright (C) 2002-2014 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License. */
12 /* along with SCIP; see the file COPYING. If not email to scip@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file pqueue.h
17  * @brief class for priority queues
18  * @author Andreas Bley
19  * @author Marc Pfetsch
20  */
21 
22 #ifndef _PQUEUE_H
23 #define _PQUEUE_H
24 
25 #include <algorithm>
26 #include <functional>
27 
28 namespace std
29 {
30  ///
31  template<typename Key,
32  typename Data,
33  typename Compare = less<Key> >
34 
35  class pqueue
36  {
37  private:
38 
39  //--------------------
40  // item node class
41  //--------------------
42  class node
43  {
44  friend class pqueue;
45 
46  //
47  node(
48  const Key& k,
49  const Data& d ):
50  key (k),
51  data (d),
52  sleft (0),
53  sright(0),
54  left (NULL),
55  right (NULL),
56  father(NULL)
57  {}
58 
59  //
60  ~node()
61  {}
62 
63  //
64  void delete_children_recursive()
65  {
66  if ( left != NULL )
67  {
68  left->delete_children_recursive();
69  delete left;
70  left = NULL;
71  }
72  if ( right != NULL )
73  {
74  right->delete_children_recursive();
75  delete right;
76  right = NULL;
77  }
78  }
79 
80  Key key;
81  Data data;
82  int sleft;
83  int sright;
84  node* left;
85  node* right;
86  node* father;
87  };
88 
89  public:
90 
91  typedef node* pqueue_item;
92 
93  private:
94 
95  node* root;
96  Compare compare;
97 
98  public:
99 
100  /** Default constructor, creates empty priority queue. */
102  root( NULL )
103  {}
104 
105  /** Destructs queue */
107  {
108  clear();
109  }
110 
111  /** Empties queue */
112  void clear()
113  {
114  if ( root != NULL )
115  {
116  root->delete_children_recursive();
117  delete root;
118  root = NULL;
119  }
120  }
121 
122  /** Returns true if the pqueue is empty. */
123  bool empty() const
124  {
125  return ( root == NULL );
126  }
127 
128  /** Returns size of queue. */
129  int size() const
130  {
131  return ( root == NULL ? 0 : root->sleft + root->sright + 1 );
132  }
133 
134  /** Returns key of queue item. */
135  const Key& get_key(
136  pqueue_item it
137  ) const
138  {
139  assert( it != NULL );
140  return it->key;
141  }
142 
143  /** Returns data of queue item. */
144  const Data& get_data(
145  pqueue_item it
146  ) const
147  {
148  assert( it != NULL );
149  return it->data;
150  }
151 
152  /** Returns queue item at top (with lowers key). */
153  pqueue_item top() const
154  {
155  return root;
156  }
157 
158  /** Inserts a new entry into the queue, returns new item */
160  const Key& key,
161  const Data& data
162  )
163  {
164  node* nn = NULL;
165  if ( root == NULL )
166  {
167  nn = new node(key,data);
168  if ( nn == NULL )
169  throw std::bad_alloc();
170  root = nn;
171  }
172  else
173  nn = create_new_node(key, data, root);
174 
175  rotate_backward(nn);
176  return nn;
177  }
178 
179  /** Reduces the key a queue item. */
181  pqueue_item item,
182  const Key& new_key
183  )
184  {
185  assert( item );
186  assert( compare(new_key, item->key) );
187 
188  item->key = new_key;
189  rotate_backward(item);
190  }
191 
192  /** Removes the topmost item from the queue. */
193  void pop()
194  {
195  assert ( root != NULL );
196  remove( root );
197  }
198 
199  /** Removes the item from the queue */
200  void remove(
201  node* item
202  )
203  {
204  assert ( item != NULL );
205  assert ( root != NULL );
206 
207  bool goto_left = ( item->left != NULL );
208  bool goto_right = ( item->right != NULL );
209  if ( goto_left && goto_right )
210  {
211  goto_right = ( compare( item->right->key, item->left->key ) );
212  goto_left = ! goto_right;
213  }
214  if ( goto_right )
215  {
216  swap_with_father( item->right );
217  remove( item );
218  return;
219  }
220  if ( goto_left )
221  {
222  swap_with_father( item->left );
223  remove( item );
224  return;
225  }
226  // at leave: remove and update all sizes
227  for (node* n = item, *f = n->father; f != NULL; n = f, f = n->father)
228  {
229  if ( f->left == n )
230  {
231  f->sleft -= 1;
232  }
233  else
234  {
235  assert( f->right == n );
236  f->sright -= 1;
237  }
238  }
239  if ( item->father )
240  {
241  if ( item->father->left == item )
242  {
243  assert( item->father->sleft == 0 );
244  item->father->left = NULL;
245  }
246  else
247  {
248  assert( item->father->right == item );
249  assert( item->father->sright == 0 );
250  item->father->right = NULL;
251  }
252  }
253  else
254  {
255  assert( item == root );
256  root = NULL;
257  }
258  delete item;
259  }
260 
261 
262  private:
263 
264  /** creates new element in the tree such that tree remains balanced */
265  node* create_new_node(
266  const Key& key,
267  const Data& data,
268  node* subproblem
269  )
270  {
271  assert( subproblem != NULL );
272 
273  if ( subproblem->sleft == 0 )
274  {
275  assert( subproblem->left == NULL );
276 
277  node* nn = new node(key,data);
278  subproblem->left = nn;
279  subproblem->sleft = 1;
280  nn->father = subproblem;
281  return nn;
282  }
283  if ( subproblem->sright == 0 )
284  {
285  assert( subproblem->right == NULL );
286 
287  node* nn = new node(key,data);
288  subproblem->right = nn;
289  subproblem->sright = 1;
290  nn->father = subproblem;
291  return nn;
292  }
293  assert( subproblem->left != NULL );
294  assert( subproblem->right != NULL );
295 
296  if ( subproblem->sleft <= subproblem->sright )
297  {
298  subproblem->sleft += 1;
299  return create_new_node(key, data, subproblem->left);
300  }
301 
302  subproblem->sright += 1;
303  return create_new_node(key, data, subproblem->right);
304  }
305 
306 
307  void swap_with_father(
308  node* n1
309  )
310  {
311  int n1_sleft = n1->sleft;
312  int n1_sright = n1->sright;
313  node* n1_left = n1->left;
314  node* n1_right = n1->right;
315  node* n1_father = n1->father;
316  assert( n1_father != NULL );
317  assert( n1_father->left == n1 || n1_father->right == n1 );
318 
319  if ( root == n1_father )
320  root = n1;
321 
322  if ( n1_father->left == n1 )
323  {
324  n1->left = n1_father;
325  n1->right = n1_father->right;
326  }
327  else
328  {
329  assert( n1_father->right == n1 );
330 
331  n1->left = n1_father->left;
332  n1->right = n1_father;
333  }
334  n1_father->left = n1_left;
335  n1_father->right = n1_right;
336 
337  n1->sleft = n1_father->sleft;
338  n1->sright = n1_father->sright;
339  n1_father->sleft = n1_sleft;
340  n1_father->sright = n1_sright;
341 
342  n1->father = n1_father->father;
343  n1_father->father = n1;
344 
345  if ( n1->left )
346  n1->left-> father = n1;
347  if ( n1->right )
348  n1->right->father = n1;
349  if ( n1_father->left )
350  n1_father->left->father = n1_father;
351  if ( n1_father->right )
352  n1_father->right->father = n1_father;
353  if ( n1->father )
354  {
355  if ( n1->father->left == n1_father )
356  n1->father->left = n1;
357  if ( n1->father->right == n1_father )
358  n1->father->right = n1;
359  }
360  }
361 
362  void rotate_backward(
363  node* item
364  )
365  {
366  assert( item != NULL );
367 
368  if ( item->father )
369  {
370  if ( ! compare( item->father->key, item->key ) )
371  {
372  swap_with_father( item );
373  rotate_backward( item );
374  }
375  }
376  }
377  };
378 
379 } // namespace std
380 
381 #endif /* _PQUEUE_H */
382