Aleph-w  1.5a.2
Biblioteca general de algoritmos y estructuras de datos
 Todo Clases Archivos Funciones Variables 'typedefs' Enumeraciones Amigas Grupos Páginas
tpl_arrayQueue.H
1 
2 # ifndef TPL_ARRAYQUEUE_H
3 # define TPL_ARRAYQUEUE_H
4 
5 # include <ahAssert.H>
6 # include <ahDefs.H>
7 # include <tpl_memArray.H>
8 
9 using namespace Aleph;
10 
11 namespace Aleph {
12 
37  template <typename T>
38 class ArrayQueue : public MemArray<T>
39 {
40 private:
41 
42  size_t front_index; // items are extracted from this point
43  size_t rear_index; // new item are inserted by this point
44 
45  void increase_index(size_t & i, const size_t inc = 1) const
46  {
47  i += inc;
48  i %= this->dim;
49  }
50 
51  T & rear_item(const size_t i = 0)
52  {
53  return this->access((size_t) (rear_index - i - 1) % this->dim);
54  }
55 
56  const T & rear_item(const size_t i = 0) const
57  {
58  return this->access((size_t) (rear_index - i - 1) % this->dim);
59  }
60 
61 public:
62 
63  void swap(ArrayQueue & q)
64  {
65  this->MemArray<T>::swap(q);
66  std::swap(front_index, q.front_index);
67  std::swap(rear_index, q.rear_index);
68  }
69 
78  ArrayQueue(const size_t sz = 8)
79  : MemArray<T>(sz), front_index(0), rear_index(0)
80  {
81  // empty
82  }
83 
84  ArrayQueue(const ArrayQueue & q)
85  : MemArray<T>(q), front_index(q.front_index), rear_index(q.rear_index)
86  {
87 
88  }
89 
91  : MemArray<T>(std::move(q)),
92  front_index(q.front_index), rear_index(q.rear_index)
93  {
94  // empty
95  }
96 
97  ArrayQueue & operator = (const ArrayQueue & q)
98  {
99  if (this == &q)
100  return *this;
101 
102  static_cast<MemArray<T>&>(*this) = q;
103 
104  front_index = q.front_index;
105  rear_index = q.rear_index;
106 
107  return *this;
108  }
109 
110  ArrayQueue & operator = (ArrayQueue && q)
111  {
112  std::swap(front_index, q.front_index);
113  std::swap(rear_index, q.rear_index);
114  static_cast<MemArray<T>*>(this)->swap(q);
115  return *this;
116  }
117 
118 private:
119 
120  T & complete_put()
121  {
122  T & ret_val = this->access(rear_index);
123  increase_index(rear_index);
124  ++this->n;
125  return ret_val;
126  }
127 
128 public:
129 
138  T & put(const T & item) throw(std::exception, std::bad_alloc)
139  {
140  if (this->expand(front_index))
141  {
142  front_index = 0;
143  rear_index = this->n;
144  }
145  this->access(rear_index) = item;
146  return complete_put();
147  }
148 
149  T & put(T && item) throw(std::exception, std::bad_alloc)
150  {
151  if (this->expand(front_index))
152  {
153  front_index = 0;
154  rear_index = this->n;
155  }
156  this->access(rear_index) = std::move(item);
157  return complete_put();
158  }
159 
176  T & putn(size_t sz) throw(std::exception, std::bad_alloc)
177  {
178  const int avail_n = this->dim - this->n;
179  if (avail_n > sz)
180  {
181  sz -= this->dim - this->n;
182  this->n = this->dim;
183  this->expand(front_index);
184  }
185 
186  increase_index(rear_index, sz);
187  this->n += sz;
188  return rear_item();
189  }
190 
199  T get() throw(std::exception, std::underflow_error, std::bad_alloc)
200  {
201  if (this->n == 0)
202  throw std::underflow_error ("queue is empty");
203 
204  T ret_val = std::move(this->access(front_index));
205  this->n--;
206  increase_index(front_index);
207 
208  if (this->contract(front_index))
209  {
210  front_index = 0;
211  rear_index = this->n;
212  }
213 
214  return ret_val;
215  }
216 
227  T & getn(const size_t i) throw(std::exception, std::underflow_error)
228  {
229  if (i >= this->n)
230  throw std::underflow_error ("queue is empty");
231 
232  this->n -= i;
233  increase_index(front_index, i);
234 
235  if (this->contract(front_index))
236  {
237  front_index = 0;
238  rear_index = this->n;
239  }
240 
241  return this->access(front_index);
242  }
243 
254  T & front(const size_t i = 0) throw(std::exception, std::range_error)
255  {
256  if (i >= this->n)
257  throw std::range_error ("index of front out of range");
258 
259  return this->access((front_index + i) % this->dim);
260  }
261 
262  const T & front(const size_t i = 0) const
263  throw(std::exception, std::range_error)
264  {
265  if (i >= this->n)
266  throw std::range_error ("index of front out of range");
267 
268  return this->access((front_index + i) % this->dim);
269  }
270 
281  T & rear(const size_t i = 0) throw(std::exception, std::range_error)
282  {
283  if (i >= this->n)
284  throw std::range_error ("index of rear out of range");
285 
286  return rear_item(i);
287  }
288 
289  const T & rear(const size_t i = 0) const
290  throw(std::exception, std::range_error)
291  {
292  if (i >= this->n)
293  throw std::range_error ("index of rear out of range");
294 
295  return rear_item(i);
296  }
297 
298  template <class Operation>
299  bool traverse(Operation & operation)
300  {
301  if (this->n == 0)
302  return true;
303 
304  for (size_t i = front_index; i != rear_index; ++i)
305  if (not operation(this->access(i)))
306  return false;
307  return true;
308  }
309 
310  template <class Operation>
311  bool traverse(Operation & operation) const
312  {
313  return const_cast<ArrayQueue*>(this)->traverse(operation);
314  }
315 
316  template <class Operation>
317  bool traverse(Operation && operation = Operation()) const
318  {
319  return traverse<Operation>(operation);
320  }
321 
322  template <class Operation>
323  bool traverse(Operation && operation = Operation())
324  {
325  return traverse<Operation>(operation);
326  }
327 
328  Functional_Methods(T);
329 
330  Generic_Items(T);
331 };
332 
355  template <typename T>
357 {
358 private:
359 
360  size_t two_pow;
361  size_t dim;
362  T * array;
363  size_t front_index; /* index of oldest inserted item */
364  size_t rear_index;
365  size_t mask;
366  size_t num_items;
367 
368  void increase_index(size_t & i, const size_t inc = 1) const
369  {
370  I( ((i + inc)%dim) == ((i+ inc)&mask) );
371 
372  i += inc;
373  i &= mask;
374  }
375 
376  T & rear_item(const size_t i = 0)
377  {
378  I(static_cast<size_t>((rear_index - i - 1) & mask) ==
379  (rear_index - i - 1)%dim);
380 
381  return array[static_cast<size_t> ((rear_index - i - 1) & mask)];
382  }
383 
384  const T & rear_item(const size_t i = 0) const
385  {
386  I(static_cast<size_t>((rear_index - i - 1) & mask) ==
387  (rear_index - i - 1)%dim);
388 
389  return array[static_cast<size_t> ((rear_index - i - 1) & mask)];
390  }
391 
392 public:
393 
394  void swap(FixedQueue & q)
395  {
396  std::swap(two_pow, q.two_pow);
397  std::swap(dim, q.dim);
398  std::swap(array, q.array);
399  std::swap(front_index, q.front_index);
400  std::swap(rear_index, q.rear_index);
401  std::swap(mask, q.mask);
402  std::swap(num_items, q.num_items);
403  }
404 
412  FixedQueue(const size_t & tp = 8)
413  : two_pow(tp), dim(1<<two_pow), array(NULL), front_index(0),
414  rear_index(0), mask(dim - 1), num_items(0)
415  {
416  array = new T [dim];
417  }
418 
421  {
422  if (array != NULL)
423  delete [] array;
424  }
425 
426  FixedQueue(const FixedQueue & q)
427  : two_pow(q.two_pow), dim(q.dim), array(new T [dim]),
428  front_index(q.front_index), rear_index(q.rear_index), mask(q.mask),
429  num_items(q.num_items)
430  {
431  for (size_t i = front_index; i != rear_index; ++i)
432  array[i] = q.array[i];
433  }
434 
436  {
437  swap(q);
438  }
439 
440  FixedQueue & operator = (const FixedQueue & q)
441  {
442  if (this == &q)
443  return *this;
444 
445  if (array != NULL)
446  delete [] array;
447 
448  new (this) FixedQueue(q);
449  return *this;
450  }
451 
452  FixedQueue & operator = (FixedQueue && q)
453  {
454  swap(q);
455  return *this;
456  }
457 
465  T & put(const T& item) throw(std::exception, std::overflow_error)
466  {
467  I(num_items < dim);
468  array[rear_index] = item;
469  T & ret_val = array[rear_index];
470  increase_index(rear_index);
471  num_items++;
472  return ret_val;
473  }
474 
475  T & put(T && item) throw(std::exception, std::overflow_error)
476  {
477  I(num_items < dim);
478  array[rear_index] = std::move(item);
479  T & ret_val = array[rear_index];
480  increase_index(rear_index);
481  num_items++;
482  return ret_val;
483  }
484 
499  T & putn(const size_t n) throw(std::exception, std::overflow_error)
500  {
501  I(num_items + n < dim);
502  increase_index(rear_index, n);
503  num_items += n;
504  return rear_item();
505  }
506 
514  T get() throw(std::exception, std::underflow_error)
515  {
516  I(num_items > 0);
517  num_items--;
518  T ret_val = std::move(array[front_index]);
519  increase_index(front_index);
520  return ret_val;
521  }
522 
532  T & getn(const size_t n) throw(std::exception, std::underflow_error)
533  {
534  I(num_items >= n);
535  num_items -= n;
536  increase_index(front_index, n);
537  return array[front_index];
538  }
539 
550  T & front(const size_t i = 0) throw(std::exception, std::range_error)
551  {
552  I(i < num_items);
553  return array[front_index + i];
554  }
555 
556  const T & front(const size_t i = 0) const
557  throw(std::exception, std::range_error)
558  {
559  I(i < num_items);
560  return array[front_index + i];
561  }
562 
572  T & rear(const size_t i = 0) throw(std::exception, std::range_error)
573  {
574  I(i < num_items);
575  return rear_item(i);
576  }
577 
578  const T & rear(const size_t i = 0) const
579  throw(std::exception, std::range_error)
580  {
581  I(i < num_items);
582  return rear_item(i);
583  }
584 
586  const size_t & size() const { return num_items; }
587 
589  bool is_empty() const { return num_items == 0; }
590 
593  const size_t & capacity() const { return dim; }
594 
595  template <class Operation>
596  bool traverse(Operation & operation)
597  {
598  if (num_items == 0)
599  return true;
600  for (size_t i = front_index; i != rear_index; ++i)
601  if (not operation(array[i]))
602  return false;
603  return true;
604  }
605 
606  template <class Operation>
607  bool traverse(Operation & operation) const
608  {
609  return const_cast<FixedQueue*>(this)->traverse(operation);
610  }
611 
612  template <class Operation>
613  bool traverse(Operation && operation = Operation()) const
614  {
615  return traverse<Operation>(operation);
616  }
617 
618  template <class Operation>
619  bool traverse(Operation && operation = Operation())
620  {
621  return traverse<Operation>(operation);
622  }
623 
624  Functional_Methods(T);
625 
626  Generic_Items(T);
627 };
628 
629 } // end namespace Aleph
630 
631 # endif /* TPL_ARRAYQUEUE_H */
632 
Definition: tpl_memArray.H:17
T & putn(size_t sz)
Definition: tpl_arrayQueue.H:176
bool is_empty() const
Retorna true si la cola está vacía.
Definition: tpl_arrayQueue.H:589
const size_t & size() const
Retorna el número de elementos que contiene la cola.
Definition: tpl_arrayQueue.H:586
T & front(const size_t i=0)
Definition: tpl_arrayQueue.H:550
Definition: tpl_arrayQueue.H:356
T & rear(const size_t i=0)
Definition: tpl_arrayQueue.H:281
T & rear(const size_t i=0)
Definition: tpl_arrayQueue.H:572
Definition: tpl_arrayQueue.H:38
T & front(const size_t i=0)
Definition: tpl_arrayQueue.H:254
T & put(const T &item)
Definition: tpl_arrayQueue.H:138
T & getn(const size_t i)
Definition: tpl_arrayQueue.H:227
const size_t & capacity() const
Definition: tpl_arrayQueue.H:593
T & putn(const size_t n)
Definition: tpl_arrayQueue.H:499
ArrayQueue(const size_t sz=8)
Definition: tpl_arrayQueue.H:78
T & getn(const size_t n)
Definition: tpl_arrayQueue.H:532
~FixedQueue()
Destructor.
Definition: tpl_arrayQueue.H:420
T & put(const T &item)
Definition: tpl_arrayQueue.H:465
FixedQueue(const size_t &tp=8)
Definition: tpl_arrayQueue.H:412

Leandro Rabindranath León