Aleph-w  1.9
General library for algorithms and data structures
tpl_arrayHeap.H
1 
2 /* Aleph-w
3 
4  / \ | | ___ _ __ | |__ __ __
5  / _ \ | |/ _ \ '_ \| '_ \ ____\ \ /\ / / Data structures & Algorithms
6  / ___ \| | __/ |_) | | | |_____\ V V / version 1.9b
7  /_/ \_\_|\___| .__/|_| |_| \_/\_/ https://github.com/lrleon/Aleph-w
8  |_|
9 
10  This file is part of Aleph-w library
11 
12  Copyright (c) 2002-2018 Leandro Rabindranath Leon & Alejandro Mujica
13 
14  This program is free software: you can redistribute it and/or modify
15  it under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  This program is distributed in the hope that it will be useful, but
20  WITHOUT ANY WARRANTY; without even the implied warranty of
21  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22  General Public License for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with this program. If not, see <https://www.gnu.org/licenses/>.
26 */
27 
28 # ifndef TPL_ARRAYHEAP_H
29 # define TPL_ARRAYHEAP_H
30 
31 # include <ahFunction.H>
32 # include <ahUtils.H>
33 # include <ahDefs.H>
34 # include <ahAssert.H>
35 # include <array_it.H>
36 # include <htlist.H>
37 # include <tpl_dynDlist.H>
38 # include <ah-args-ctor.H>
39 # include <ahDry.H>
40 # include <ah-dry.H>
41 
42 using namespace Aleph;
43 
44 namespace Aleph {
45 
46 
47  template <typename T, class Compare> inline
48  T & sift_up(T * ptr, const size_t l, const size_t r, Compare & cmp)
49  {
50  size_t i = r;
51  for (size_t p; i > l; i = p)
52  {
53  p = u_index(i); // índice del padre (c = i/2)
54  if (cmp(ptr[p], ptr[i])) // ¿cumple propiedad orden?
55  return ptr[i]; // si, todo el arreglo es un heap
56 
57  std::swap(ptr[p], ptr[i]); // intercambie y restaure nivel p
58  }
59 
60  return ptr[i];
61  }
62 
63  template <typename T, class Compare> inline
64  void sift_down(T * ptr, const size_t l, const size_t r, Compare & cmp)
65  {
66  size_t i = l, c;
67  while (true)
68  {
69  c = l_index(i); // índice del hijo izquierdo (c = i/2)
70  if (c > r) // ¿hay hijo izquierdo?
71  return; // no ==> termine
72 
73  if (c + 1 <= r) // ¿hay hijo derecho?
74  if (cmp (ptr[c + 1], ptr[c])) // sí ==> escoja menor
75  c++;
76 
77  if (cmp (ptr[i], ptr[c])) // ¿cumple propiedad orden?
78  return; // sí ==> termine
79 
80  std::swap(ptr[c], ptr[i]);
81  i = c;
82  }
83  }
84 
85  template <typename T, class Compare> inline
86  void sift_down_up(T * ptr, const size_t l, const size_t i, const size_t r,
87  Compare & cmp)
88  {
89  sift_down <T, Compare> (ptr, i, r, cmp);
90  sift_up <T, Compare> (ptr, l, i, cmp);
91  }
92 
114  template <typename T, class Compare = Aleph::less<T>> inline
115  void heapsort(T * array, const size_t n, Compare cmp = Compare())
116  {
118 
119  --array; //desplazar posición hacia atrás ==> array[1] == primero
120  for (size_t i = 2; i <= n; ++i)
121  sift_up <T, Aleph::Inversed_Compare<T, Compare>> (array, 1, i, inv_cmp);
122  for (size_t i = n; i > 1; --i)
123  {
124  std::swap(array[1], array[i]); // poner en raíz i-ésimo item
125  sift_down<T,Aleph::Inversed_Compare<T,Compare>>(array, 1, i - 1, inv_cmp);
126  }
127  }
128 
150  template <typename T, class Compare = Aleph::less<T>> inline
151  void faster_heapsort(T * array, const size_t n, Compare cmp = Compare())
152  {
154 
155  --array; // desplazar posición hacia atrás ==> array[1] == primero
156  for (size_t i = n/2; i >= 1; --i)
157  sift_down(array, i, n, inv_cmp);
158  for (size_t i = n; i > 1; --i)
159  {
160  std::swap(array[1], array[i]); // poner en raíz i-ésimo item
161  sift_down(array, 1, i - 1, inv_cmp);
162  }
163  }
164 
167  template <typename T, class Compare = Aleph::less<T>>
168  bool valid_heap(T * array, const size_t l, const size_t r,
169  Compare cmp = Compare())
170  {
171  size_t i;
172  for (i = l_index(l) /* i = 2*l */; i <= r; i++)
173  if (cmp(array[i], array[u_index (i)]))
174  break;
175  return i > r;
176  }
177 
191  template <typename T, class Compare = Aleph::less<T>>
192  class ArrayHeap : public LocateFunctions<ArrayHeap<T, Compare>, T>,
193  public FunctionalMethods<ArrayHeap<T, Compare>, T>,
194  public GenericItems<ArrayHeap<T, Compare>, T>,
195  public EqualToMethod<ArrayHeap<T, Compare>>,
196  public StlAlephIterator<ArrayHeap<T, Compare>>
197  {
198  T * array = nullptr;
199  mutable size_t dim;
200  size_t num_items = 0;
201 
202  mutable bool array_allocated = true;
203 
204  Compare cmp;
205 
206  static size_t r_index(const size_t & i)
207  {
208  return (i << 1) + 1; // multiplica i por 2 y suma 1
209  }
210 
211  public:
212 
213  void swap(ArrayHeap & h)
214  {
215  std::swap(array, h.array);
216  std::swap(dim, h.dim);
217  std::swap(num_items, h.num_items);
218  std::swap(array_allocated, h.array_allocated);
219  std::swap(cmp, h.cmp);
220  }
221 
222  using Item_Type = T;
223 
224  using Key_Type = T;
225 
226  Special_Ctors(ArrayHeap, T);
227 
228  Args_Ctor(ArrayHeap, T);
229 
231  ArrayHeap(const size_t d = 1024, Compare __cmp = Compare())
232  : array(nullptr), dim(d), num_items(0), array_allocated(false), cmp(__cmp)
233  {
234  array = new T [d + 1];
235  array_allocated = true;
236  }
237 
239  ArrayHeap(T * ptr, const size_t & d, Compare __cmp = Compare())
240  : array(ptr), dim(d), num_items(0), array_allocated(false), cmp(__cmp)
241  {
242  // empty
243  }
244 
245  ArrayHeap(const ArrayHeap & h)
246  : dim(h.dim), num_items(h.num_items), cmp(h.cmp)
247  {
248  array = new T [dim + 1];
249  for (size_t i = 1; i <= num_items; ++i)
250  array[i] = h.array[i];
251  }
252 
253  ArrayHeap(ArrayHeap && h) noexcept
254  : array_allocated(false), cmp(h.cmp)
255  {
256  swap(h);
257  }
258 
259  ArrayHeap & operator = (const ArrayHeap & h)
260  {
261  if (this == &h)
262  return *this;
263 
264  if (dim < h.dim)
265  {
266  T * ptr = new T [h.dim + 1];
267  if (array_allocated)
268  delete [] array;
269  array = ptr;
270  array_allocated = true;
271  dim = h.dim;
272  }
273 
274  for (size_t i = 1; i <= h.num_items; ++i)
275  array[i] = h.array[i];
276  num_items = h.num_items;
277  cmp = h.cmp;
278 
279  return *this;
280  }
281 
282  ArrayHeap & operator = (ArrayHeap && h)
283  {
284  swap(h);
285  return *this;
286  }
287 
289  virtual ~ArrayHeap()
290  {
291  if (array_allocated and array != nullptr)
292  delete [] array;
293  }
294 
296  T & top()
297  {
298  if (num_items == 0)
299  throw std::underflow_error("Heap is empty");
300 
301  return array[1];
302  }
303 
304  T & insert_ne(const T & key) noexcept
305  {
306  array[++num_items] = key; // colocar nuevo elemento
307  return sift_up(array, 1, num_items, cmp);
308  }
309 
310  T & insert_ne(T && key) noexcept
311  {
312  array[++num_items] = std::move(key); // colocar nuevo elemento
313  return sift_up(array, 1, num_items, cmp);
314  }
315 
325  T & insert(const T & key)
326  {
327  if (num_items >= dim)
328  throw std::overflow_error("Heap out of capacity");
329  return insert_ne(key);
330  }
331 
332  T & insert(T && key)
333  {
334  if (num_items >= dim)
335  throw std::overflow_error("Heap out of capacity");
336  return insert_ne(std::forward<T>(key));
337  }
338 
339  T & put(const T & key) { return insert(key); }
340 
341  T & append(const T & key) { return insert(key); }
342 
343  T & put(T && key) { return insert(std::forward<T>(key)); }
344 
345  T & append(T && key) { return insert(std::forward<T>(key)); }
346 
356  T getMin()
357  {
358  if (num_items == 0)
359  throw std::underflow_error("Heap is empty");
360 
361  T ret_val = array[1];
362  array[1] = array[num_items--];
363  sift_down(array, 1, num_items, cmp);
364  return ret_val;
365  }
366 
368  T get()
369  {
370  return getMin();
371  }
372 
374  T getMax()
375  {
376  return getMin();
377  }
378 
380  const size_t & size() const { return num_items; }
381 
383  bool is_empty() const { return num_items == 0; }
384 
402  void update(T & data)
403  {
404  assert(&data >= &array[0] and &data <= &array[dim]);
405 
406  const size_t i = &data - array;
407  sift_down_up(array, 1, i, num_items, cmp);
408  sift_up(array, i, num_items, cmp);
409  }
410 
411  void remove(T & item)
412  {
413  item = array[num_items--];
414  update(item);
415  }
416 
418  T & operator [] (const size_t i)
419  {
420  return array[i];
421  }
422 
423  struct Iterator : public Array_Iterator<T>
424  {
425  Iterator(const ArrayHeap & h) noexcept
426  : Array_Iterator<T>(no_exception_ctor, h.array + 1, h.dim, h.num_items)
427  { /* empty */ }
428  };
429 
430  private:
431 
432  // super fast array traversal
433  template <class Operation>
434  bool __traverse(Operation & operation)
435  {
436  for (size_t i = 1; i <= num_items; ++i)
437  if (not operation(array[i]))
438  return false;
439 
440  return true;
441  }
442 
443  public:
444 
445  template <class Operation>
446  bool traverse(Operation & operation) const
447  {
448  return const_cast<ArrayHeap&>(*this).__traverse(operation);
449  }
450 
451  template <class Operation>
452  bool traverse(Operation & operation)
453  {
454  return __traverse(operation);
455  }
456 
457  template <class Operation>
458  bool traverse(Operation && operation = Operation()) const
459  {
460  return const_cast<ArrayHeap&>(*this).__traverse(operation);
461  }
462 
463  template <class Operation>
464  bool traverse(Operation && operation = Operation())
465  {
466  return traverse(operation);
467  }
468  };
469 
470 } // end namespace Aleph
471 # endif /* TPL_ARRAYHEAP_H */
472 
void update(T &data)
Definition: tpl_arrayHeap.H:402
Definition: htlist.H:450
Definition: htlist.H:1290
T getMax()
Definition: tpl_arrayHeap.H:374
Definition: htlist.H:133
Definition: tpl_arrayHeap.H:192
bool is_empty() const
Retorna true si el heap está vacío.
Definition: tpl_arrayHeap.H:383
T getMin()
Definition: tpl_arrayHeap.H:356
virtual ~ArrayHeap()
Destructor.
Definition: tpl_arrayHeap.H:289
T & operator[](const size_t i)
Retorna la i-ésima entrada del heap.
Definition: tpl_arrayHeap.H:418
ArrayHeap(T *ptr, const size_t &d, Compare __cmp=Compare())
Constructor con arreglo y dimensión.
Definition: tpl_arrayHeap.H:239
Definition: array_it.H:45
Definition: ah-comb.H:35
T & top()
Retorna el menor elemento del heap.
Definition: tpl_arrayHeap.H:296
ArrayHeap(const size_t d=1024, Compare __cmp=Compare())
Constructor con dimensión por omisión.
Definition: tpl_arrayHeap.H:231
const size_t & size() const
Retorna la cantidad de elementos.
Definition: tpl_arrayHeap.H:380
T & insert(const T &key)
Definition: tpl_arrayHeap.H:325
Definition: ahFunction.H:969
Definition: htlist.H:1323

Leandro Rabindranath León