Aleph-w  1.9
General library for algorithms and data structures
Multiset.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  Aleph implementation of multiset C++ standard container
29 */
30 
31 # ifndef AH_MULTISET_H
32 # define AH_MULTISET_H
33 
34 # include <memory>
35 # include <ah_stdc++_utils.H>
36 # include <tpl_dnode.H>
37 # include <tpl_treapRk.H>
38 # include <tpl_nodePool.H>
39 
40 namespace Aleph
41 {
42 
64  template <class T,
65  class Compare = Aleph::less<T>,
66  template <class, class> class Tree = Treap_Rk
67  >
68 class multiset
69 {
70  struct Node_Data
71  {
72  mutable T key;
73  mutable size_t num_reps;
74 
75  Node_Data() : num_reps(0) { /* empty */ }
76 
77  Node_Data(const T & k) : key(k), num_reps(1) { /* empty */ }
78  };
79 
80  struct Cmp_Data
81  {
82  bool operator () (const Node_Data & op1, const Node_Data & op2) const
83  {
84  return Compare () (op1.key, op2.key);
85  }
86  };
87 
88 public:
89 
91  typedef T value_type;
92 
94  typedef typename multiset::value_type & reference;
95 
97  typedef const typename multiset::value_type & const_reference;
98 
100  typedef size_t size_type;
101 
103  typedef T key_type;
104 
105 private:
106 
107  typedef Tree<Node_Data, Cmp_Data> Tree_Type;
108 
109  typedef typename Tree_Type::Node Node;
110 
111  typedef typename Tree_Type::Iterator Tree_Iterator;
112 
113  mutable Tree_Type tree;
114 
115  mutable size_t num_elem;
116 
117  Node_Pool<Node> pool;
118 
119  static T & get_key(Node * p) { return KEY(p).key; }
120 
121  static size_t & get_num_reps(Node * p) { return KEY(p).num_reps; }
122 
123 public:
124 
129  class iterator
130  {
131  private:
132 
133  friend class multiset<T, Compare, Tree>;
134 
135  typedef typename Tree_Type::Iterator Iterator;
136 
137  mutable multiset * multiset_ptr = nullptr;
138 
139  mutable Iterator tree_it;
140 
141  mutable int pos_in_node;
142 
143  bool overflow;
144  bool underflow;
145 
146  iterator (multiset * mset_ptr, Node * curr_tree_node, int pos = 0)
147  : multiset_ptr(mset_ptr), tree_it(mset_ptr->tree, curr_tree_node),
148  pos_in_node(pos), overflow (false), underflow (false)
149  {
150  // empty
151  }
152 
153  void default_init ()
154  {
155  if (tree_it.has_curr ())
156  {
157  underflow = overflow = false;
158  pos_in_node = 0;
159  }
160  else
161  underflow = overflow = true;
162  }
163 
164  iterator(const multiset & ms)
165  : multiset_ptr(const_cast<multiset*>(&ms)), tree_it(ms.tree)
166  {
167  default_init();
168  }
169 
170  Node * get_curr_node() { return tree_it.get_curr(); }
171 
172  bool has_curr() const
173  {
174  return tree_it.has_curr();
175  }
176 
177  Node_Data & get_data() { return KEY(get_curr_node()); }
178 
179  T & get_key() { return multiset::get_key(get_curr_node()); }
180 
181  size_t & get_num_reps() { return multiset::get_num_reps(get_curr_node()); }
182 
183  public:
184 
187 
191 
193  typedef typename multiset<T>::value_type * pointer;
194 
197 
199  typedef const typename multiset<T>::reference const_reference;
200 
201  iterator(multiset * mset_ptr)
202  : multiset_ptr(mset_ptr), tree_it(multiset_ptr->tree)
203  {
204  default_init();
205  }
206 
207  iterator(const iterator & it)
208  : multiset_ptr(it.multiset_ptr), tree_it(it.tree_it),
209  pos_in_node(it.pos_in_node),
210  overflow(it.overflow), underflow(it.underflow)
211  {
212  // empty
213  }
214 
217  {
218  underflow = overflow = true;
219  pos_in_node = -1;
220  }
221 
223  const T & operator * ()
224  {
225  return get_key();
226  }
227 
229  const T * operator -> ()
230  {
231  return & get_key();
232  }
233 
234  private:
235 
236  void goto_begin ()
237  {
238  tree_it.reset_first ();
239  if (tree_it.has_curr ())
240  {
241  underflow = false;
242  pos_in_node = 0;
243  }
244  else
245  {
246  underflow = true;
247  pos_in_node = -1;
248  }
249  }
250 
251  void goto_last ()
252  {
253  tree_it.reset_last ();
254  if (tree_it.has_curr ())
255  {
256  overflow = false;
257  pos_in_node = get_num_reps() - 1;
258  }
259  else
260  {
261  overflow = true;
262  pos_in_node = -1;
263  }
264  }
265 
266  void goto_end ()
267  {
268  tree_it.reset_last();
269  if (tree_it.has_curr())
270  { // el árbol no está vacío
271  tree_it.next (); // coloca tree_it fuera de rango
272  underflow = false;
273  }
274  else
275  underflow = true;
276 
277  pos_in_node = -1;
278  overflow = true;
279  }
280 
281  iterator compute_end() const
282  {
283  iterator it(*this);
284  it.goto_end();
285  return it;
286  }
287 
288  bool is_at_end() const
289  {
290  return not tree_it.has_curr();
291  }
292 
293  iterator compute_begin() const
294  {
295  iterator it(*this);
296  return it;
297  }
298 
299  void forward ()
300  {
301  if (underflow)
302  {
303  goto_begin ();
304  return;
305  }
306 
307  if (++pos_in_node == get_num_reps())
308  {
309  tree_it.next ();
310 
311  if (tree_it.has_curr ())
312  pos_in_node = 0;
313  else
314  {
315  overflow = true;
316  pos_in_node = -1;
317  assert(*this == compute_end());
318  }
319  }
320  }
321 
322  void backward ()
323  {
324  if (overflow)
325  {
326  goto_last ();
327  return;
328  }
329 
330  if (pos_in_node-- == 0)
331  {
332  tree_it.prev ();
333 
334  if (tree_it.has_curr ())
335  pos_in_node = get_num_reps();
336  else
337  underflow = true;
338  }
339  }
340 
341  void del()
342  {
343  Node * tree_node = get_curr_node();
344  size_t & num_reps = multiset::get_num_reps(tree_node);
345 
346  --num_reps;
347 
348  --multiset_ptr->num_elem;
349 
350  if (num_reps == 0)
351  {
352  tree_it.del();
353  multiset_ptr->pool.deallocate(tree_node);
354 
355  if (tree_it.has_curr ())
356  pos_in_node = 0;
357  else
358  {
359  overflow = true;
360  pos_in_node = -1;
361  }
362  }
363  }
364 
365  public:
366 
369  iterator operator ++ ()
370  {
371  forward ();
372  return *this;
373  }
374 
376  iterator operator ++ (int)
377  {
378  iterator ret_val = *this;
379  forward ();
380  return ret_val;
381  }
382 
385  iterator operator -- ()
386  {
387  backward ();
388  return *this;
389  }
390 
392  T & operator -- (int)
393  {
394  iterator ret_val = *this;
395  backward ();
396  return ret_val;
397  }
398 
401  iterator operator += (size_type n)
402  {
403  for (int i = 0; i < n; ++i)
404  forward ();
405 
406  return *this;
407  }
408 
411  iterator operator -= (size_type n)
412  {
413  for (int i = 0; i < n; ++i)
414  backward ();
415 
416  return *this;
417  }
418 
420  bool operator == (const iterator & it) const
421  {
422  if (this->has_curr() and it.has_curr())
423  return pos_in_node == it.pos_in_node;
424 
425  if (this->is_at_end() and it.is_at_end())
426  {
427  assert(this->overflow and it.overflow);
428  return true;
429  }
430 
431  return false;
432  }
433 
435  bool operator != (const iterator & itor) const
436  {
437  return not (*this == itor);
438  }
439 
440  bool verify (const multiset & _multiset) const
441  {
442  return tree_it.verify ( (Tree_Type*)& (_multiset.tree));
443  }
444 
445  bool verify (const iterator & it) const
446  {
447  return tree_it.verify (it.tree_it);
448  }
449  }; // class iterator;
450 
453 
456 
459 
461  multiset () : num_elem (0), pool(100) { /* empty */ }
462 
463 private:
464 
465  void copy (const multiset & c)
466  {
467  tree.getRoot () = copyRec(c.tree.getRoot());
468  }
469 
470 public:
471 
473  multiset (const multiset & c) : num_elem (c.num_elem), pool(100)
474  {
475  copy (c);
476  }
477 
493  template <typename Itor>
494  multiset (Itor beg, const Itor & end) : multiset()
495  {
496  while (beg != end)
497  insert (*beg++);
498  }
499 
503  {
504  destroyRec(tree.getRoot());
505  }
506 
509  {
510  if (this == &c)
511  return *this;
512 
513  destroyRec(tree.getRoot());
514 
515  copy(c);
516 
517  num_elem = c.num_elem;
518 
519  return *this;
520  }
521 
523  size_type size () const { return num_elem; }
524 
526  bool empty () const
527  {
528  return COUNT(tree.getRoot ()) == 0;
529  }
530 
533  bool operator == (const multiset & c) const
534  {
535  if (this == &c)
536  return true;
537 
538  if (size () != c.size ())
539  return false;
540 
541  Tree_Iterator itor1 (tree), itor2 (c.tree);
542 
543  while (itor1.has_curr() and itor2.has_curr())
544  {
545  Node * p1 = itor1.get_curr();
546  Node * p2 = itor2.get_curr();
547 
548  if (no_equals <Node_Data, Cmp_Data> (KEY(p1), KEY(p2)))
549  return false;
550  else if (get_num_reps(p1) != get_num_reps(p2))
551  return false;
552 
553  itor1.next ();
554  itor2.next ();
555  }
556 
557  return not itor1.has_curr() and not itor2.has_curr();
558  }
559 
562  bool operator != (const multiset & c) const
563  {
564  return not (*this == c);
565  }
566 
569  bool operator < (const multiset & c) const
570  {
571  if (this == &c)
572  return false;
573 
574  iterator itor1 (*this), itor2 (c);
575 
576  while (itor1.has_curr() and itor2.has_curr())
577  {
578  if (Cmp_Data () (itor1.get_data(), itor2.get_data()))
579  return true;
580  else if (Cmp_Data () (itor2.get_data(), itor1.get_data()))
581  return false; // no son iguales
582 
583  itor1.forward();
584  itor2.forward();
585  }
586 
587  if (itor1.has_curr()) /* |*this| >= |c| */
588  return false;
589 
590  return itor2.has_curr();
591  }
592 
595  bool operator > (const multiset & c) const
596  {
597  return not (*this == c or *this < c);
598  }
599 
602  bool operator <= (const multiset & c) const
603  {
604  return not (*this > c );
605  }
606 
609  bool operator >= (const multiset & c) const
610  {
611  return not (*this < c);
612  }
613 
621  size_type count (const T & value) const
622  {
623  Node * p = tree.search (Node_Data(value));
624 
625  if (p == nullptr)
626  return 0;
627 
628  return get_num_reps(p);
629  }
630 
648  iterator find (const T & value) const
649  {
650  Node * node = tree.search(Node_Data(value));
651 
652  if (node == nullptr)
653  return end ();
654 
655  return iterator(const_cast<multiset*>(this), node);
656  }
657 
673  iterator lower_bound (const T & value) const
674  {
675  if (size () == 0)
676  throw std::underflow_error ("multiset is empty");
677 
678  Node * tree_node = tree.search(Node_Data(value));
679 
680  if (tree_node == nullptr)
681  return end ();
682 
683  return iterator (this, tree_node);
684  }
685 
701  iterator upper_bound (const T & value) const
702  {
703  if (size () == 0)
704  throw std::underflow_error("multiset is empty");
705 
706  Node * tree_node = tree.search(Node_Data(value));
707 
708  if (tree_node == nullptr)
709  return end ();
710 
711  iterator it (this, tree_node);
712  it.list_it.reset_last ();
713 
714  return it;
715  }
716 
719  void swap (multiset & c)
720  {
721  std::swap (tree.getRoot (), c.tree.getRoot ());
722  std::swap (num_elem, c.num_elem);
723  }
724 
727  iterator begin () const
728  {
729  return iterator (*this);
730  }
731 
734  iterator end () const
735  {
736  return iterator(*this).compute_end();
737  }
738 
748  iterator insert (const T & value)
749  {
750  Node * p = pool.allocate(Node_Data(value));
751  Node * ptr = tree.search_or_insert(p);
752 
753  if (ptr != p) // ya está value en el árbol
754  pool.deallocate(p);
755 
756  ++num_elem;
757 
758  return iterator(this, ptr, get_num_reps(ptr)++);
759  }
760 
786  iterator insert (iterator pos, const T & value)
787  {
788  Aleph::verify_container_and_iterator (this, pos);
789 
790  if (pos != pos.compute_end())
791  {
792  Node * p = pos.get_curr_node();
793 
794  if (are_equals <Node_Data, Cmp_Data> (KEY(p), Node_Data(value)))
795  {
796  get_num_reps(p)++;
797  pos.pos_in_node++;
798 
799  return pos;
800  }
801  }
802 
803  return insert(value);
804  }
805 
823  template <typename Itor>
824  void insert (Itor beg, const Itor & end)
825  {
826  Aleph::verify_iterators (beg, end);
827 
828  while (beg != end)
829  insert(*beg++);
830  }
831 
840  size_type erase (const T & value)
841  {
842  Node * tree_node = tree.remove(Node_Data(value));
843 
844  if (tree_node == nullptr)
845  return 0;
846 
847  const size_t ret_val = get_num_reps(tree_node);
848 
849  pool.deallocate(tree_node);
850 
851  num_elem -= ret_val;
852 
853  return ret_val;
854  }
855 
869  void erase (iterator pos)
870  {
871  Aleph::verify_container_and_iterator (*this, pos);
872 
873  Node * tree_node = pos.get_curr_node();
874 
875  size_t & num_reps = get_num_reps(tree_node);
876 
877  --num_reps;
878  --num_elem;
879 
880  if (num_reps == 0)
881  {
882  tree.remove(Node_Data(KEY(tree_node)));
883  pool.deallocate(tree_node);
884  }
885  }
886 
887 private:
888 
889  /* Borra el rango secuencialmente */
890  iterator delete_range (iterator beg, const iterator & end)
891  {
892  while (beg != end)
893  beg.del();
894 
895  return beg;
896  }
897 
898 public:
899 
913  iterator erase (iterator beg, const iterator & end)
914  {
915  Aleph::verify_container_and_iterator (*this, beg);
916  Aleph::verify_iterators (beg, end);
917 
918  return delete_range(beg, end);
919  }
920 
922  void clear ()
923  {
924  destroyRec (static_cast<Node *> (tree.getRoot ()));
925  num_elem = 0;
926  }
927 };
928 
929 
930  template <typename T>
931 typename iterator_traits<typename multiset<T>::iterator>::difference_type
932 distance (typename multiset<T>::iterator it1,
933  typename multiset<T>::iterator it2)
934 {
935  typename iterator_traits<typename multiset<T>::iterator>::difference_type
936  counter = 0;
937 
938 
939  while (it1 != it2)
940  {
941  ++counter;
942  ++it1;
943  }
944 
945  return counter;
946 }
947 
948 } // end namespace Aleph
949 
950 # endif // AH_MULTISET_H
Definition: Multiset.H:129
multiset< T >::value_type * pointer
Tipo apuntador a elemento dentro del multi-conjunto.
Definition: Multiset.H:193
Definition: tpl_nodePool.H:45
bool operator>(const multiset &c) const
Definition: Multiset.H:595
multiset::iterator const_iterator
Tipo iterador constante.
Definition: Multiset.H:452
void deallocate(Node *p) noexcept
Definition: tpl_nodePool.H:102
size_t size_type
Tipo numérico para los tamaños (natural).
Definition: Multiset.H:100
bool operator<=(const multiset &c) const
Definition: Multiset.H:602
auto & COUNT(Node *p) noexcept
Definition: tpl_binNodeXt.H:66
multiset()
Constructor vacío de un multi-conjunto.
Definition: Multiset.H:461
iterator insert(iterator pos, const T &value)
Definition: Multiset.H:786
iterator upper_bound(const T &value) const
Definition: Multiset.H:701
multiset::value_type & reference
Tipo genérico de referencia a elemento del conjunto.
Definition: Multiset.H:94
void swap(multiset &c)
Definition: Multiset.H:719
void erase(iterator pos)
Definition: Multiset.H:869
multiset(const multiset &c)
Instancia una copia del multi-conjunto c.
Definition: Multiset.H:473
bool operator<(const multiset &c) const
Definition: Multiset.H:569
multiset & operator=(const multiset &c)
Asigna todo el contenido de c a this.
Definition: Multiset.H:508
multiset< T >::value_type value_type
El tipo de dato que contiene el multi-conjunto.
Definition: Multiset.H:186
T key_type
El tipo dato de los elementos del conjunto.
Definition: Multiset.H:103
~multiset()
Definition: Multiset.H:502
Node::Key_Type & KEY(Node *p) noexcept
Definition: tpl_binNode.H:318
iterator lower_bound(const T &value) const
Definition: Multiset.H:673
size_type size() const
Retorna la cantidad de elementos que contiene el multi-conjunto.
Definition: Multiset.H:523
size_type count(const T &value) const
Definition: Multiset.H:621
Definition: ah-comb.H:35
bool operator>=(const multiset &c) const
Definition: Multiset.H:609
Definition: Multiset.H:68
iterator erase(iterator beg, const iterator &end)
Definition: Multiset.H:913
void insert(Itor beg, const Itor &end)
Definition: Multiset.H:824
void destroyRec(Node *&root) noexcept
Definition: tpl_binNodeUtils.H:500
Definition: tpl_treapRk.H:1010
iterator end() const
Definition: Multiset.H:734
T value_type
El tipo dato de los elementos del conjunto.
Definition: Multiset.H:91
multiset::iterator const_reverse_iterator
Tipo iterador invertido constante.
Definition: Multiset.H:458
iterator find(const T &value) const
Definition: Multiset.H:648
void clear()
Borra todos los elementos del multi-conjunto.
Definition: Multiset.H:922
iterator insert(const T &value)
Definition: Multiset.H:748
Node * copyRec(Node *root)
Definition: tpl_binNodeUtils.H:519
multiset< T >::size_type difference_type
Definition: Multiset.H:190
bool operator==(const multiset &c) const
Definition: Multiset.H:533
Node * allocate()
Definition: tpl_nodePool.H:56
multiset::iterator reverse_iterator
Tipo iterador invertido.
Definition: Multiset.H:455
iterator begin() const
Definition: Multiset.H:727
bool empty() const
Retorna true si el contenedor esta vacío.
Definition: Multiset.H:526
iterator()
Constructor vacío; no tiene validez si no se asocia un conjunto.
Definition: Multiset.H:216
multiset(Itor beg, const Itor &end)
Definition: Multiset.H:494
multiset< T >::reference reference
Tipo referencia a elemento dentro del multi-conjunto.
Definition: Multiset.H:196
const multiset::value_type & const_reference
Tipo genérico de referencia constante a elemento del conjunto.
Definition: Multiset.H:97
bool operator!=(const multiset &c) const
Definition: Multiset.H:562
size_type erase(const T &value)
Definition: Multiset.H:840
const multiset< T >::reference const_reference
Tipo referencia a elemento dentro del multi-conjunto.
Definition: Multiset.H:199

Leandro Rabindranath León