Aleph-w  1.9
General library for algorithms and data structures
tpl_dynArrayHeap.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 # ifndef TPL_DYNARRAYHEAP_H
28 # define TPL_DYNARRAYHEAP_H
29 
30 # include <tpl_dynArray.H>
31 
32 namespace Aleph {
33 
34 
35  template <typename T, class Compare> inline
36  void sift_up(DynArray<T> & a, size_t l, size_t r, Compare & cmp) noexcept
37  {
38  for (size_t p, i = r; i > l; i = p)
39  {
40  p = u_index(i);
41  T & ap = a.access(p);
42  T & ai = a.access(i);
43  if (cmp (ap, ai)) // ¿cumple propiedad orden?
44  return; // si, todo el arreglo es un heap
45 
46  std::swap(ap, ai); // intercambie y restaure nivel p
47  }
48  }
49 
50  template <typename T, class Compare> inline
51  void sift_down(DynArray<T> & a, size_t l, size_t r, Compare & cmp) noexcept
52  {
53  size_t i = l, c;
54  while (true)
55  {
56  c = l_index(i); // índice del hijo izquierdo (c = i/2)
57  if (c > r) // ¿hay hijo izquierdo?
58  return; // no ==> termine
59 
60  T * ac = & a.access(c);
61  if (c + 1 <= r) // ¿hay hijo derecho?
62  {
63  T * ac1 = & a.access(c + 1);
64  if (cmp(*ac1, *ac)) // sí ==> escoja menor
65  {
66  c++;
67  ac = ac1;
68  }
69  }
70 
71  T & ai = a.access(i);
72  if (cmp(ai, *ac)) // ¿cumple propiedad orden?
73  return; // sí ==> termine
74 
75  std::swap(*ac, ai);
76  i = c;
77  }
78  }
79 
80 
94  template <typename T, class Compare = Aleph::less<T>>
95  class DynArrayHeap : public LocateFunctions<DynArrayHeap<T, Compare>, T>,
96  public FunctionalMethods<DynArrayHeap<T, Compare>, T>,
97  public GenericKeys<DynArrayHeap<T, Compare>, T>,
98  public EqualToMethod<DynArrayHeap<T, Compare>>,
99  public StlAlephIterator<DynArrayHeap<T, Compare>>
100  {
101  DynArray<T> array;
102  size_t num_items = 0;
103 
104  Compare cmp;
105 
106  static size_t r_index(const size_t & i) noexcept
107  {
108  return (i << 1) + 1; // multiplica i por 2 y suma 1
109  }
110 
111  public:
112 
113  using Item_Type = T;
114 
116  DynArrayHeap(Compare __cmp = Compare()) : num_items(0), cmp(__cmp)
117  {
118  // empty
119  }
120 
121  Special_Ctors(DynArrayHeap, T);
122 
123  Args_Ctor(DynArrayHeap, T);
124 
126  T & top()
127  {
128  if (num_items == 0)
129  throw std::underflow_error("Heap is empty");
130 
131  return array.access(1);
132  }
133 
143  T & insert(const T & key)
144  {
145  array.touch(++num_items) = key; // colocar nuevo elemento
146  sift_up(array, 1, num_items, cmp); // restaurar propiedad orden
147  return array.access(num_items);
148  }
149 
150  T & insert(T && key)
151  {
152  array.touch(++num_items) = move(key); // colocar nuevo elemento
153  sift_up(array, 1, num_items, cmp); // restaurar propiedad orden
154  return array.access(num_items);
155  }
156 
157  void reserve(size_t n)
158  {
159  if (num_items > n)
160  throw out_of_range("DynArrayHeap: n is greater than current heap size");
161  array.reserve(n);
162  }
163 
164  T & insert_direct(const T & key) noexcept
165  {
166  array(++num_items) = key; // colocar nuevo elemento
167  sift_up(array, 1, num_items, cmp); // restaurar propiedad orden
168  return array.access(num_items);
169  }
170 
171  T & insert_direct(T && key) noexcept
172  {
173  array(++num_items) = move(key); // colocar nuevo elemento
174  sift_up(array, 1, num_items, cmp); // restaurar propiedad orden
175  return array.access(num_items);
176  }
177 
178  T & put(const T & key) { return insert(key); }
179 
180  T & put(T && key) { return insert(std::forward<T>(key)); }
181 
182  T & append(const T & key) { return insert(key); }
183 
184  T & append(T && key) { return insert(std::forward<T>(key)); }
185 
195  T getMin()
196  {
197  if (num_items == 0)
198  throw std::underflow_error("Heap is empty");
199 
200  T & a1 = array(1);
201  T ret_val = move(a1);
202  a1 = move(array(num_items--));
203  sift_down(array, 1, num_items, cmp); // propiedad orden
204 
205  array.cut(num_items + 1);
206 
207  return ret_val;
208  }
209 
211  T get()
212  {
213  return getMin();
214  }
215 
217  T getMax()
218  {
219  return getMin();
220  }
221 
223  const size_t & size() const noexcept { return num_items; }
224 
226  bool is_empty() const noexcept { return num_items == 0; }
227 
228  struct Iterator : DynArray<T>::Iterator
229  {
230  using Base = typename DynArray<T>::Iterator;
231 
232  Iterator(const DynArrayHeap & h) noexcept : Base(h.array)
233  {
234  if (h.num_items != 0)
235  this->next_ne();
236  }
237 
238  Iterator() noexcept { /* empty */ }
239 
240  bool has_curr() const noexcept
241  {
242  return this->curr_idx != 0 and this->curr_idx != this->array_ptr->size();
243  }
244 
245  long get_pos() const noexcept { return this->Base::get_pos() - 1; }
246  };
247 
248  template <class Operation>
249  bool traverse(Operation & operation) noexcept(noexcept(operation))
250  {
251  for (Iterator it(*this); it.has_curr(); it.next_ne())
252  if (not operation(it.get_curr_ne()))
253  return false;
254  return true;
255  }
256 
257  template <class Operation>
258  bool traverse(Operation & operation) const noexcept(noexcept(operation))
259  {
260  return const_cast<DynArrayHeap&>(*this).traverse<Operation>(operation);
261  }
262 
263  template <class Operation>
264  bool traverse(Operation && operation = Operation()) const
265  noexcept(noexcept(operation))
266  {
267 
268  return traverse<Operation>(operation);
269  }
270 
271  template <class Operation>
272  bool traverse(Operation && operation = Operation())
273  noexcept(noexcept(operation))
274  {
275  return traverse<Operation>(operation);
276  }
277  };
278 
279 
280 
281 } // end namespace Aleph
282 
283 # endif // TPL_DYNARRAYHEAP_H
Definition: htlist.H:450
Definition: htlist.H:1290
void reserve(const size_t l, const size_t r)
Definition: tpl_dynArray.H:998
Definition: htlist.H:133
void cut(const size_t new_dim=0)
Definition: tpl_dynArray.H:1104
Definition: tpl_dynArrayHeap.H:95
T & access(const size_t i) const noexcept
Definition: tpl_dynArray.H:874
T & touch(const size_t i)
Definition: tpl_dynArray.H:958
T getMin()
Definition: tpl_dynArrayHeap.H:195
bool is_empty() const noexcept
Retorna true si el heap está vacío.
Definition: tpl_dynArrayHeap.H:226
DynArrayHeap(Compare __cmp=Compare())
Constructor con dimensión por omisión.
Definition: tpl_dynArrayHeap.H:116
T & insert(const T &key)
Definition: tpl_dynArrayHeap.H:143
T & top()
Retorna el menor elemento del heap.
Definition: tpl_dynArrayHeap.H:126
Definition: ah-comb.H:35
T getMax()
Definition: tpl_dynArrayHeap.H:217
const size_t & size() const noexcept
Retorna la cantidad de elementos.
Definition: tpl_dynArrayHeap.H:223
size_t size() const noexcept
Definition: tpl_dynArray.H:641
Definition: tpl_dynArray.H:159
Definition: tpl_dynArray.H:1258
Definition: htlist.H:1323

Leandro Rabindranath León