yat  0.21pre
Ranking.h
1 #ifndef theplu_yat_utility_ranking
2 #define theplu_yat_utility_ranking
3 
4 // $Id: Ranking.h 4087 2021-08-30 02:00:02Z peter $
5 
6 /*
7  Copyright (C) 2021 Peter Johansson
8 
9  This file is part of the yat library, http://dev.thep.lu.se/yat
10 
11  The yat library is free software; you can redistribute it and/or
12  modify it under the terms of the GNU General Public License as
13  published by the Free Software Foundation; either version 3 of the
14  License, or (at your option) any later version.
15 
16  The yat library is distributed in the hope that it will be useful,
17  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19  General Public License for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with yat. If not, see <http://www.gnu.org/licenses/>.
23 */
24 
25 #include "ranking/Impl.h"
26 #include "ranking/Iterator.h"
27 #include "ranking/NodeBase.h"
28 #include "ranking/NodeValue.h"
29 
30 #include "yat_assert.h"
31 
32 #include <cstddef>
33 #include <functional>
34 #include <iostream>
35 #include <iterator>
36 #include <memory>
37 
38 namespace theplu {
39 namespace yat {
40 namespace utility {
41 
48  template<typename T, class Compare = std::less<T> >
49  class Ranking
50  {
51  public:
53  typedef T value_type;
55  typedef Compare key_compare;
57  typedef const T& reference;
59  typedef const T& const_reference;
61  typedef const T* pointer;
63  typedef const T* const_pointer;
65  typedef size_t size_type;
67  typedef ranking::Iterator<T> iterator;
69  typedef ranking::Iterator<T> const_iterator;
71  typedef std::reverse_iterator<iterator> reverse_iterator;
73  typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
74 
78  Ranking(void) = default;
79 
83  ~Ranking(void)
84  {
85  clear();
86  }
87 
91  Ranking(const Compare& c)
92  : compare_(c)
93  {
94  YAT_ASSERT(validate());
95  }
96 
97 
101  Ranking(const Ranking& other);
102 
106  Ranking(Ranking&& other);
107 
111  Ranking& operator=(const Ranking& other);
112 
116  Ranking& operator=(Ranking&& other);
117 
118 
124  {
125  return iterator(impl_.left_most());
126  }
127 
128 
132  const_iterator begin(void) const
133  {
134  return cbegin();
135  }
136 
137 
141  const_iterator cbegin(void) const
142  {
143  return const_iterator(impl_.left_most());
144  }
145 
146 
150  iterator end(void)
151  {
152  return iterator(&impl_.head_);
153  }
154 
155 
159  const_iterator end(void) const
160  {
161  return cend();
162  }
163 
164 
168  const_iterator cend(void) const
169  {
170  return const_iterator(&impl_.head_);
171  }
172 
173 
179  {
180  return reverse_iterator(end());
181  }
182 
183 
188  {
189  return reverse_iterator(begin());
190  }
191 
192 
197  {
198  return crend();
199  }
200 
201 
206  {
207  return crbegin();
208  }
209 
210 
215  {
216  return const_reverse_iterator(cend());
217  }
218 
223  {
224  return const_reverse_iterator(cbegin());
225  }
226 
227 
231  void clear(void)
232  {
233  if (size()) {
234  YAT_ASSERT(root_node() != head_node());
235  erase(root_node());
236  }
237  impl_.reset();
238  }
239 
240 
244  const Compare& compare(void) const
245  {
246  return compare_;
247  }
248 
249 
253  bool empty(void) const
254  {
255  return impl_.empty();
256  }
257 
258 
267  iterator erase(const_iterator position);
268 
275  size_type erase(const T& value);
276 
286 
294  const_iterator find(const T& x) const;
295 
296 
304  iterator insert(const T& element)
305  {
306  std::unique_ptr<ranking::NodeValue<T>>
307  newnode(new ranking::NodeValue<T>(element));
308  return insert(std::move(newnode));
309  }
310 
311 
318  iterator insert(T&& element)
319  {
320  std::unique_ptr<ranking::NodeValue<T>>
321  newnode(new ranking::NodeValue<T>(std::move(element)));
322  return insert(std::move(newnode));
323  }
324 
325 
333  iterator insert(const_iterator hint, const T& element)
334  {
335  std::unique_ptr<ranking::NodeValue<T>>
336  newnode(new ranking::NodeValue<T>(element));
337  return insert(hint, std::move(newnode));
338  }
339 
340 
347  iterator insert(const_iterator hint, T&& element)
348  {
349  std::unique_ptr<ranking::NodeValue<T>>
350  newnode(new ranking::NodeValue<T>(std::move(element)));
351  return insert(hint, std::move(newnode));
352  }
353 
354 
362  template<typename InputIterator>
363  void insert(InputIterator first, InputIterator last)
364  {
365  for (; first!=last; ++first)
366  insert(end(), *first);
367  }
368 
369 
375  const_iterator lower_bound(const T& x) const
376  {
377  if (empty())
378  return cend();
379  return lower_bound(root_node(), head_node(), x);
380  }
381 
382 
388  const_iterator upper_bound(const T& x) const
389  {
390  if (empty())
391  return cend();
392  return upper_bound(root_node(), head_node(), x);
393  }
394 
395 
401  size_t ranking(const_iterator it) const
402  {
403  YAT_ASSERT(it.node_);
404  return impl_.ranking(it.node_);
405  }
406 
407 
413  size_t size(void) const
414  {
415  return impl_.size();
416  }
417 
418  private:
419  Compare compare_;
420  // Things that are agnostic to T are implemented in impl_.
421  ranking::Impl impl_;
422 
423  iterator
424  insert_and_rebalance(std::unique_ptr<ranking::NodeValue<T>>&& element,
425  ranking::NodeBase& parent, bool left)
426  {
427  iterator result(element.get());
428  impl_.insert_and_rebalance(std::move(element), parent, left);
429  YAT_ASSERT(validate());
430  return result;
431  }
432 
433 
434 
435  void print(const ranking::NodeBase* p, std::ostream& os) const
436  {
437  if (p) {
438  if (p->is_head_node()==false) {
439  print(p->right_, os);
440  }
441  os << std::string(p->generation()*4, ' ');
442  if (!p->is_head_node())
443  os << value(p);
444  else
445  os << "H";
446  os << ", H=" << ranking::height(p) << ", S=" << ranking::size(p);
447  os << ": "
448  << p->parent_ << " "
449  << p << " "
450  << p->left_ << " "
451  << p->right_ << "\n";
452  if (p->is_head_node()==false) {
453  print(p->left_, os);
454  }
455  if (p->parent_ && !p->is_left_node() && !p->is_right_node()) {
456  os << "print error: " << p << "\n";
457  exit(1);
458  }
459  }
460  }
461 
462  // return a copy of x but with children and parent set to nullptr.
463  ranking::NodeValue<T>*
464  clone_node(const ranking::NodeValue<T>* x) const;
465 
472  ranking::NodeValue<T>* copy(const Ranking& other);
473 
477  ranking::NodeValue<T>* copy(const ranking::NodeValue<T>* root) const;
478 
482  void erase_node(const_iterator position);
483 
484  // return the root node
485  const ranking::NodeValue<T>* root_node(void) const
486  {
487  return static_cast<const ranking::NodeValue<T>*>(impl_.root_node());
488  }
489 
490 
491  ranking::NodeValue<T>* root_node(void)
492  {
493  return static_cast<ranking::NodeValue<T>*>(impl_.root_node());
494  }
495 
496 
497  const ranking::NodeBase* head_node(void) const
498  {
499  return &impl_.head_;
500  }
501 
502 
503  ranking::NodeBase* head_node(void)
504  {
505  return &impl_.head_;
506  }
507 
508 
509  const ranking::NodeValue<T>*
510  left(const ranking::NodeBase* x) const
511  {
512  YAT_ASSERT(x->left_ != &impl_.head_);
513  return static_cast<const ranking::NodeValue<T>*>(x->left_);
514  }
515 
516 
517  ranking::NodeValue<T>*
518  left(ranking::NodeBase* x) const
519  {
520  YAT_ASSERT(x->left_ != &impl_.head_);
521  return static_cast<ranking::NodeValue<T>*>(x->left_);
522  }
523 
524 
525  const ranking::NodeValue<T>*
526  right(const ranking::NodeBase* x) const
527  {
528  YAT_ASSERT(x->right_ != &impl_.head_);
529  return static_cast<const ranking::NodeValue<T>*>(x->right_);
530  }
531 
532 
533  ranking::NodeValue<T>*
534  right(ranking::NodeBase* x) const
535  {
536  YAT_ASSERT(x->right_ != &impl_.head_);
537  return static_cast<ranking::NodeValue<T>*>(x->right_);
538  }
539 
540 
541  // delete x and its offsprings
542  void erase(ranking::NodeValue<T>* x) const
543  {
544  while (x) {
545  if (x->right_)
546  erase(right(x));
547  ranking::NodeValue<T>* tmp = left(x);
548  delete x;
549  x = tmp;
550  }
551  }
552 
553 
558  iterator insert(std::unique_ptr<ranking::NodeValue<T>>&& element)
559  {
560 
561  if (empty()) {
562  element->parent_ = &impl_.head_;
563  impl_.root_node() = element.release();
564  impl_.head_.left_ = impl_.root_node();
565  impl_.head_.right_ = impl_.root_node();
566  impl_.right_most() = impl_.root_node();
567  impl_.head_.update_height();
568  impl_.head_.update_size();
569 
570  YAT_ASSERT(impl_.root_node()->parent_);
571  YAT_ASSERT(impl_.root_node()->parent_ == &impl_.head_);
572  YAT_ASSERT(impl_.root_node()->is_left_node());
573 
574  YAT_ASSERT(validate());
575  return iterator(root_node());
576  }
577 
578  return insert(impl_.root_node(), std::move(element));
579  }
580 
581 
582  // Insert \a element into the subtree in which x is the root.
583  iterator insert(ranking::NodeBase* x,
584  std::unique_ptr<ranking::NodeValue<T>>&& element)
585  {
586  YAT_ASSERT(x);
587  YAT_ASSERT(!x->is_head_node());
588 
589  while (true) {
590  ranking::NodeBase* parent = x;
591  if (compare_(element->value(), value(x))) {
592  x = x->left_;
593  if (x == nullptr)
594  return insert_and_rebalance(std::move(element), *parent, true);
595  }
596  else {
597  x = x->right_;
598  if (x == nullptr)
599  return insert_and_rebalance(std::move(element), *parent, false);
600  }
601  }
602  YAT_ASSERT(0 && "we can't reach here");
603  return iterator(element.get());
604  }
605 
606 
608  std::unique_ptr<ranking::NodeValue<T>>&& element)
609  {
610  // special case when hint == end()
611  if (hint.node_ == head_node()) {
612  YAT_ASSERT(hint == cend());
613  if (empty() || compare_(element->value(), value(impl_.right_most())))
614  return insert(std::move(element));
615  return insert_and_rebalance(std::move(element), *impl_.right_most(),
616  false);
617  }
618 
619  YAT_ASSERT(hint != end());
620 
621  // value <= hint i.e. !(hint<value)
622  if (!compare_(*hint, element->value())) {
623  // if hint == begin
624  if (hint.node_ == impl_.left_most()) {
625  YAT_ASSERT(hint == cbegin());
626  return insert_and_rebalance(std::move(element),
627  *impl_.left_most(),
628  true);
629  }
630 
631  // prev <= value <= hint insert
632  YAT_ASSERT(hint != cbegin());
633  auto before = std::prev(hint);
634  if (!compare_(element->value(), *before)) {
635  return insert(const_cast<ranking::NodeBase*>(hint.node_),
636  std::move(element));
637  }
638  else {
639  return insert(std::move(element));
640  }
641  }
642  // else value > hint
643  else {
644  YAT_ASSERT(compare_(*hint, element->value()));
645  // hint == rightmost
646  if (hint.node_ == impl_.right_most()) {
647  return insert_and_rebalance(std::move(element),
648  *impl_.right_most(),
649  false);
650  }
651  auto after = std::next(hint);
652  YAT_ASSERT(after != cend());
653  // hint < value <= after
654  if (!compare_(*after, element->value())) {
655  return insert(const_cast<ranking::NodeBase*>(after.node_),
656  std::move(element));
657  }
658  }
659 
660  return insert(std::move(element));
661  }
662 
663 
664  /*
665  Find the first node that is greater or equal to key, i.e., all
666  elements left of returned node are less than key.
667  */
669  lower_bound(const ranking::NodeValue<T>* x, const ranking::NodeBase* y,
670  const T& key) const
671  {
672  // x is used to traverse the tree
673  // y holds the result
674 
675  while (x) {
676  // key is less (or equal) than x, store x as potential result
677  // and search in left branch
678  if (!compare_(x->value(), key)) {
679  y = x;
680  x = left(x);
681  }
682  // key is greater than x, the lower bound is not x; it is
683  // either in the right branch or a previously assigned
684  // ancestor. Do not store x as potential result, but search
685  // branch.
686  else
687  x = right(x);
688  }
689  // x has reached a leaf, and the result should be stored in y
690 
691  // returned node is not smaller than key
692  YAT_ASSERT(y==head_node() || !compare_(value(y), key));
693  // all nodes left of returned node are smaller than key
694  YAT_ASSERT(y->left_==nullptr ||
695  compare_(value(y->left_->right_most()), key));
696  return const_iterator(y);
697  }
698 
699 
700  const ranking::NodeValue<T>* parent(const ranking::NodeBase* x) const
701  {
702  YAT_ASSERT(x);
703  YAT_ASSERT(x->parent_);
704  YAT_ASSERT(x->parent_ != &impl_.head_);
705  return static_cast<const ranking::NodeValue<T>*>(x->parent_);
706  }
707 
708 
709  ranking::NodeValue<T>* parent(ranking::NodeBase* x) const
710  {
711  YAT_ASSERT(x);
712  YAT_ASSERT(x->parent_);
713  YAT_ASSERT(x->parent_ != &impl_.head_);
714  return static_cast<ranking::NodeValue<T>*>(x->parent_);
715  }
716 
717 
718  /*
719  Find the first node that is greater than key, i.e., all
720  elements left of returned node are less or equal to key.
721  */
723  upper_bound(const ranking::NodeValue<T>* x, const ranking::NodeBase* y,
724  const T& key) const
725  {
726  // x is used to traverse the tree
727  // y holds the result
728 
729  while (x) {
730  // key is less than x value, x is a potential upper_bound,
731  // store and search in left
732  if (compare_(key, x->value())) {
733  y = x;
734  x = left(x);
735  }
736  else {
737  // key is greater (or equal) than x, x is not the upper
738  // bound. It is either in the right branch or in a
739  // previously assigned ancestor (current y).
740  x = right(x);
741  }
742  }
743  // x has reached a leaf, and the result should be stored in y
744 
745  // key is less than returned node
746  YAT_ASSERT(y==head_node() || compare_(key, value(y)));
747  // all nodes left of returned node are smaller (or equal) than
748  // key, i.e., key is not smaller than any of the nodes to the
749  // left of returned node.
750  YAT_ASSERT(y->left_==nullptr ||
751  !compare_(key, value(y->left_->right_most())));
752  return const_iterator(y);
753  }
754 
755 
756  const T& value(const ranking::NodeBase* p) const
757  {
758  YAT_ASSERT(p);
759  YAT_ASSERT(!p->is_head_node());
760  return static_cast<const ranking::NodeValue<T>*>(p)->value();
761  }
762 
763 
764  bool validate(void) const
765  {
766 #ifndef YAT_DEBUG_RANKING
767  return true;
768 #else
769  if (!impl_.validate()) {
770  std::cerr << "Impl::validate failed\n";
771  return false;
772  }
773 
774  bool ok = true;
775  size_t rank = 0;
776  YAT_ASSERT(cbegin().node_);
777  YAT_ASSERT(cend().node_);
778  for (auto it = cbegin(); it!=cend(); ++it) {
779  size_t r = ranking(it);
780  if (r != rank) {
781  std::cerr << "ranking: " << r << "; expected: " << rank << "\n";
782  std::cerr << "size: " << it.node_->size_ << "\n";
783  std::cerr << it.node_->parent_ << " "
784  << it.node_->is_left_node() << " "
785  << it.node_->is_right_node() << "\n---\n";
786  ok = false;
787  }
788  ++rank;
789  }
790  return ok;
791 #endif
792  }
793  };
794 
795  // avoid doxygen reading code below as it has problems to to match
796  // declarations and implementations unless matching perfectly.
797 
799 
800  // implementations
801  template<typename T, typename C>
802  Ranking<T,C>::Ranking(const Ranking& other)
803  : compare_(other.compare())
804  {
805  if (!other.empty())
806  impl_.root_node() = copy(other);
807  YAT_ASSERT(validate());
808  }
809 
810 
811  template<typename T, typename C>
812  Ranking<T,C>::Ranking(Ranking&& other)
813  : compare_(std::move(other.compare())), impl_(std::move(other.impl_))
814  {
815  YAT_ASSERT(validate());
816  }
817 
818 
819  template<typename T, typename C>
820  Ranking<T, C>& Ranking<T, C>::operator=(const Ranking& other)
821  {
822  if (this != &other) {
823  Ranking tmp(other);
824  *this = std::move(tmp);
825  }
826  return *this;
827  }
828 
829 
830  template<typename T, typename C>
831  Ranking<T, C>& Ranking<T, C>::operator=(Ranking&& other)
832  {
833  clear();
834  compare_ = std::move(other.compare_);
835  impl_ = std::move(other.impl_);
836  return *this;
837  }
838 
839 
840  template<typename T, typename C>
841  ranking::NodeValue<T>* Ranking<T,C>::copy(const Ranking& other)
842  {
843  YAT_ASSERT(other.root_node());
844  ranking::NodeValue<T>* root = copy(other.root_node());
845  root->parent_ = head_node();
846  head_node()->left_ = root;
847  head_node()->right_ = root->left_most();
848  head_node()->update_height();
849  head_node()->update_size();
850  if (root_node())
851  impl_.right_most() = root_node()->right_most();
852  else
853  impl_.right_most() = head_node();
854  YAT_ASSERT(validate());
855  return root;
856  }
857 
858 
859  template<typename T, typename C>
860  ranking::NodeValue<T>*
861  Ranking<T,C>::copy(const ranking::NodeValue<T>* x) const
862  {
863  YAT_ASSERT(x);
864  ranking::NodeValue<T>* root = clone_node(x);
865  YAT_ASSERT(root);
866  root->height_ = x->height_;
867  root->size_ = x->size_;
868 
869  try {
870  if (x->left_) {
871  root->left_ = copy(left(x));
872  root->left_->parent_ = root;
873  }
874  if (x->right_) {
875  root->right_ = copy(right(x));
876  root->right_->parent_ = root;
877  }
878  }
879  catch (std::exception& e) {
880  erase(root);
881  std::rethrow_exception(std::current_exception());
882  }
883  return root;
884  }
885 
886 
887  template<typename T, typename C>
888  ranking::NodeValue<T>*
889  Ranking<T,C>::clone_node(const ranking::NodeValue<T>* x) const
890  {
891  YAT_ASSERT(x);
892  ranking::NodeValue<T>* res = new ranking::NodeValue<T>(x->value());
893  res->left_ = nullptr;
894  res->right_ = nullptr;
895  res->parent_ = nullptr;
896  return res;
897  }
898 
899 
900  template<typename T, typename C>
901  void Ranking<T, C>::erase_node(typename Ranking<T, C>::const_iterator p)
902  {
903  YAT_ASSERT(p != end());
904  const ranking::NodeBase* node = p.node_;
905  YAT_ASSERT(node);
906 
907  impl_.erase_and_rebalance(node);
908  delete node;
909  YAT_ASSERT(validate());
910  return;
911  }
912 
913 
914  template<typename T, typename C>
915  typename Ranking<T, C>::iterator
917  {
918  YAT_ASSERT(p != end());
919  const_iterator res = p;
920  ++res;
921  erase_node(p);
922  // iterator and const_iterator are same at the moment
923  return res;
924  }
925 
926 
927  template<typename T, typename C>
928  typename Ranking<T, C>::size_type Ranking<T, C>::erase(const T& value)
929  {
930  auto it = lower_bound(value);
931  typename Ranking<T, C>::size_type n = 0;
932  while (it!=end() && !compare_(value, *it)) {
933  erase_node(it++);
934  ++n;
935  }
936  return n;
937  }
938 
939 
940  template<typename T, typename C>
941  typename Ranking<T, C>::iterator
943  typename Ranking<T, C>::const_iterator last)
944  {
945  if (first == cbegin() && last == cend())
946  clear();
947  else
948  while (first != last) {
949  erase_node(first++);
950  }
951  return last;
952  }
953 
954 
955  template<typename T, typename C>
956  typename Ranking<T, C>::const_iterator Ranking<T, C>::find(const T& x) const
957  {
958  auto it = lower_bound(x);
959  if (it != cend() && compare_(x, *it))
960  it = cend();
961  return it;
962  }
963 
965 
966 }}} // of namespace utility, yat, and theplu
967 #endif
reverse_iterator rbegin(void)
Definition: Ranking.h:178
iterator insert(const T &element)
insert an element
Definition: Ranking.h:304
const_iterator cbegin(void) const
Definition: Ranking.h:141
const Compare & compare(void) const
Definition: Ranking.h:244
std::reverse_iterator< const_iterator > const_reverse_iterator
reverse iterator
Definition: Ranking.h:73
iterator begin(void)
Definition: Ranking.h:123
const_reverse_iterator rend(void) const
Definition: Ranking.h:196
const_iterator lower_bound(const T &x) const
Definition: Ranking.h:375
iterator insert(const_iterator hint, T &&element)
insert with hint
Definition: Ranking.h:347
const_iterator end(void) const
Definition: Ranking.h:159
The Department of Theoretical Physics namespace as we define it.
iterator end(void)
Definition: Ranking.h:150
Definition: stl_utility.h:64
void clear(std::vector< T > &vec)
reduce size and capacity to zero
Definition: stl_utility.h:493
const_iterator begin(void) const
Definition: Ranking.h:132
const_iterator find(const T &x) const
Compare key_compare
type used to compare elements
Definition: Ranking.h:55
T value_type
value type
Definition: Ranking.h:53
iterator erase(const_iterator position)
~Ranking(void)
Destructor.
Definition: Ranking.h:83
ranking::Iterator< T > const_iterator
iterator
Definition: Ranking.h:69
ranking::Iterator< T > iterator
iterator
Definition: Ranking.h:67
iterator insert(const_iterator hint, const T &element)
insert with hint
Definition: Ranking.h:333
void clear(void)
Definition: Ranking.h:231
const_iterator cend(void) const
Definition: Ranking.h:168
Definition: Ranking.h:49
const T & reference
reference
Definition: Ranking.h:57
reverse_iterator rend(void)
Definition: Ranking.h:187
bool empty(void) const
Definition: Ranking.h:253
Ranking & operator=(const Ranking &other)
assignment operator
const_reverse_iterator crbegin(void) const
Definition: Ranking.h:214
Ranking(const Compare &c)
Definition: Ranking.h:91
const_reverse_iterator rbegin(void) const
Definition: Ranking.h:205
iterator insert(T &&element)
insert an element
Definition: Ranking.h:318
Ranking(void)=default
Default constructor.
const T & const_reference
reference
Definition: Ranking.h:59
size_t ranking(const_iterator it) const
Definition: Ranking.h:401
const T * pointer
pointer
Definition: Ranking.h:61
size_t size(void) const
Definition: Ranking.h:413
const T * const_pointer
const pointer
Definition: Ranking.h:63
size_t size_type
size type
Definition: Ranking.h:65
const_reverse_iterator crend(void) const
Definition: Ranking.h:222
std::reverse_iterator< iterator > reverse_iterator
reverse iterator
Definition: Ranking.h:71
void insert(InputIterator first, InputIterator last)
insert range
Definition: Ranking.h:363
const_iterator upper_bound(const T &x) const
Definition: Ranking.h:388

Generated on Wed Jan 25 2023 03:34:29 for yat by  doxygen 1.8.14