ORIGINAL
Loading...
Searching...
No Matches
skipList.h
Go to the documentation of this file.
1#ifndef SKIPLIST_H
2#define SKIPLIST_H
3#include <random>
4#include "comparator.h"
5#include "vector.h"
6#include "couple.h"
7
25
26namespace original {
27
41 template<typename K_TYPE,
42 typename V_TYPE,
43 typename ALLOC = allocator<K_TYPE>,
45 class skipList {
46 protected:
57
58 using rebind_alloc_pointer = typename ALLOC::template rebind_alloc<skipListNode*>;
59 public:
60 friend class skipList;
61
69 explicit skipListNode(const K_TYPE& key = K_TYPE{}, const V_TYPE& value = V_TYPE{},
70 u_integer levels = 1, std::initializer_list<skipListNode*> next = {});
71
77
83
88 const K_TYPE& getKey() const;
89
94 const V_TYPE& getValue() const;
95
100 V_TYPE& getValue();
101
106 [[nodiscard]] u_integer getLevels() const;
107
112 void expandLevels(u_integer new_levels);
113
118 void shrinkLevels(u_integer new_levels);
119
124 void setValue(const V_TYPE& value);
125
132
138 void setPNext(u_integer levels, skipListNode* next);
139
146 static void connect(u_integer levels, skipListNode* prev, skipListNode* next);
147 };
148
149 using rebind_alloc_node = typename ALLOC::template rebind_alloc<skipListNode>;
150 using rebind_alloc_pointer = typename ALLOC::template rebind_alloc<skipListNode*>;
151
153 skipListNode* head_;
156 mutable std::mt19937 gen_{std::random_device{}()};
157 mutable std::uniform_real_distribution<floating> dis_{0.0, 1.0};
158
164 class Iterator {
165 protected:
167
172 explicit Iterator(skipListNode* cur = nullptr);
173
175 Iterator(const Iterator& other);
176
179
184 [[nodiscard]] bool hasNext() const;
185
189 void next() const;
190
195 Iterator* clone() const;
196
201 void operator+=(integer steps) const;
202
208 integer operator-(const Iterator& other) const;
209
215
221
226 [[nodiscard]] bool isValid() const;
227
234 static integer ptrDistance(const Iterator* start, const Iterator* end);
235 };
236
237 friend Iterator;
238
248 skipListNode* createNode(const K_TYPE& key = K_TYPE{}, const V_TYPE& value = V_TYPE{},
249 u_integer levels = 1, std::initializer_list<skipListNode*> next = {}) const;
250
256 void destroyNode(skipListNode* node) const;
257
265 bool highPriority(skipListNode* cur, skipListNode* next) const;
266
274 bool highPriority(const K_TYPE& key, skipListNode* next) const;
275
282 static bool equal(const K_TYPE& key, skipListNode* next);
283
289
295
300 void expandCurLevels(u_integer new_levels);
301
306 void shrinkCurLevels(u_integer new_levels);
307
312 skipListNode* listCopy() const;
313
318 skipListNode* findLastNode() const;
319
324 explicit skipList(Compare compare = Compare{});
325
332 skipListNode* find(const K_TYPE& key) const;
333
340 bool modify(const K_TYPE& key, const V_TYPE& value);
341
349 bool insert(const K_TYPE& key, const V_TYPE& value);
350
357 bool erase(const K_TYPE& key);
358
363 void listDestroy() noexcept;
364
370 };
371}
372
373template <typename K_TYPE, typename V_TYPE, typename ALLOC, typename Compare>
374original::skipList<K_TYPE, V_TYPE, ALLOC, Compare>::skipListNode::skipListNode(const K_TYPE& key, const V_TYPE& value,
375 u_integer levels, std::initializer_list<skipListNode*> next)
376 : data_({key, value}), next_(vector<skipListNode*>(levels, rebind_alloc_pointer{}, nullptr)) {
377 if (next.size() != 0 && static_cast<u_integer>(next.size()) != levels) {
378 throw outOfBoundError();
379 }
380 u_integer i = 0;
381 for (auto&& ptr: next) {
382 this->next_[i] = ptr;
383 i += 1;
384 }
385}
386
387template <typename K_TYPE, typename V_TYPE, typename ALLOC, typename Compare>
388original::couple<const K_TYPE, V_TYPE>&
392
393template <typename K_TYPE, typename V_TYPE, typename ALLOC, typename Compare>
398
399template <typename K_TYPE, typename V_TYPE, typename ALLOC, typename Compare>
400const K_TYPE&
402 return this->data_.template get<0>();
403}
404
405template <typename K_TYPE, typename V_TYPE, typename ALLOC, typename Compare>
406const V_TYPE&
408 return this->data_.template get<1>();
409}
410
411template <typename K_TYPE, typename V_TYPE, typename ALLOC, typename Compare>
412V_TYPE&
414 return this->data_.template get<1>();
415}
416
417template <typename K_TYPE, typename V_TYPE, typename ALLOC, typename Compare>
421
422template<typename K_TYPE, typename V_TYPE, typename ALLOC, typename Compare>
424 if (this->getLevels() >= new_levels){
425 return;
426 }
427 auto increment = new_levels - this->getLevels();
428 for (u_integer i = 0; i < increment; ++i) {
429 this->next_.pushEnd(nullptr);
430 }
431}
432
433template<typename K_TYPE, typename V_TYPE, typename ALLOC, typename Compare>
435 if (new_levels >= this->getLevels() || new_levels == 0){
436 return;
437 }
438 auto decrement = this->getLevels() - new_levels;
439 for (u_integer i = 0; i < decrement; ++i) {
440 this->next_.popEnd();
441 }
442}
443
444template <typename K_TYPE, typename V_TYPE, typename ALLOC, typename Compare>
446 this->data_.template set<1>(value);
447}
448
449template <typename K_TYPE, typename V_TYPE, typename ALLOC, typename Compare>
452 return this->next_[levels - 1];
453}
454
455template <typename K_TYPE, typename V_TYPE, typename ALLOC, typename Compare>
457{
458 this->next_[levels - 1] = next;
459}
460
461template <typename K_TYPE, typename V_TYPE, typename ALLOC, typename Compare>
463{
464 if (prev) {
465 prev->setPNext(levels, next);
466 }
467}
468
469template<typename K_TYPE, typename V_TYPE, typename ALLOC, typename Compare>
472
473template<typename K_TYPE, typename V_TYPE, typename ALLOC, typename Compare>
477
478template<typename K_TYPE, typename V_TYPE, typename ALLOC, typename Compare>
481 if (this == &other){
482 return *this;
483 }
484
485 this->cur_ = other.cur_;
486 return *this;
487}
488
489template<typename K_TYPE, typename V_TYPE, typename ALLOC, typename Compare>
491 return this->cur_->getPNext(1);
492}
493
494template<typename K_TYPE, typename V_TYPE, typename ALLOC, typename Compare>
496 this->cur_ = this->cur_->getPNext(1);
497}
498
499template<typename K_TYPE, typename V_TYPE, typename ALLOC, typename Compare>
504
505template<typename K_TYPE, typename V_TYPE, typename ALLOC, typename Compare>
507 if (steps < 0){
509 }
510
511 for (integer i = 0; i < steps; ++i) {
512 this->next();
513 }
514}
515
516template<typename K_TYPE, typename V_TYPE, typename ALLOC, typename Compare>
519 if (const integer pos_dis = ptrDistance(&other, this);
520 pos_dis != std::numeric_limits<integer>::max()) return pos_dis;
521 if (const integer neg_dis = ptrDistance(this, &other);
522 neg_dis != std::numeric_limits<integer>::max()) return -neg_dis;
523 return this->cur_ > other.cur_ ?
524 std::numeric_limits<integer>::max() :
525 std::numeric_limits<integer>::min();
526}
527
528template<typename K_TYPE, typename V_TYPE, typename ALLOC, typename Compare>
531 if (!this->isValid()){
532 throw outOfBoundError();
533 }
534
535 return this->cur_->getVal();
536}
537
538template<typename K_TYPE, typename V_TYPE, typename ALLOC, typename Compare>
541 if (!this->isValid()){
542 throw outOfBoundError();
543 }
544
545 return this->cur_->getVal();
546}
547
548template<typename K_TYPE, typename V_TYPE, typename ALLOC, typename Compare>
552
553template<typename K_TYPE, typename V_TYPE, typename ALLOC, typename Compare>
556 auto s = ownerPtr(start->clone());
557 auto e = ownerPtr(end->clone());
558 integer dis = 0;
559 while (s->isValid()){
560 if (s->cur_ == e->cur_){
561 return dis;
562 }
563 dis += 1;
564 s->next();
565 }
566 if (e->isValid()){
567 dis = std::numeric_limits<integer>::max();
568 }
569 return dis;
570}
571
572template <typename K_TYPE, typename V_TYPE, typename ALLOC, typename Compare>
575 std::initializer_list<skipListNode*> next) const {
576 auto node = this->rebind_alloc.allocate(1);
577 this->rebind_alloc.construct(node, key, value, levels, next);
578 return node;
579}
580
581template <typename K_TYPE, typename V_TYPE, typename ALLOC, typename Compare>
583 this->rebind_alloc.destroy(node);
584 this->rebind_alloc.deallocate(node, 1);
585}
586
587template <typename K_TYPE, typename V_TYPE, typename ALLOC, typename Compare>
589{
590 if (!cur){
591 return false;
592 }
593 return this->highPriority(cur->getKey(), next);
594}
595
596template <typename K_TYPE, typename V_TYPE, typename ALLOC, typename Compare>
598{
599 if (!next){
600 return true;
601 }
602 return this->compare_(key, next->getKey());
603}
604
605template <typename K_TYPE, typename V_TYPE, typename ALLOC, typename Compare>
607{
608 if (!next) {
609 return false;
610 }
611
612 return key == next->getKey();
613}
614
615template <typename K_TYPE, typename V_TYPE, typename ALLOC, typename Compare>
617{
618 constexpr floating p = 0.5;
619 u_integer levels = 1;
620 while (this->dis_(this->gen_) < p) {
621 levels += 1;
622 }
623 return levels;
624}
625
626template<typename K_TYPE, typename V_TYPE, typename ALLOC, typename Compare>
629 return this->head_->getLevels();
630}
631
632template<typename K_TYPE, typename V_TYPE, typename ALLOC, typename Compare>
634 this->head_->expandLevels(new_levels);
635}
636
637template<typename K_TYPE, typename V_TYPE, typename ALLOC, typename Compare>
639 this->head_->shrinkLevels(new_levels);
640}
641
642template <typename K_TYPE, typename V_TYPE, typename ALLOC, typename Compare>
645 auto copied_head =
646 this->createNode(this->head_->getKey(), this->head_->getValue(), this->getCurLevels());
647
648 vector<skipListNode*> copied_curs{this->getCurLevels(), rebind_alloc_pointer{}, copied_head};
649 auto src_cur = this->head_;
650 while (src_cur->getPNext(1)){
651 auto src_next = src_cur->getPNext(1);
652 auto copied_next = this->createNode(src_next->getKey(), src_next->getValue(), src_next->getLevels());
653 for (u_integer i = 0; i < src_next->getLevels(); ++i) {
654 skipListNode::connect(i + 1, copied_curs[i], copied_next);
655 copied_curs[i] = copied_next;
656 }
657 src_cur = src_next;
658 }
659
660 return copied_head;
661}
662
663template<typename K_TYPE, typename V_TYPE, typename ALLOC, typename Compare>
666 auto cur = this->head_;
667 while (cur->getPNext(1)){
668 cur = cur->getPNext(1);
669 }
670 return cur;
671}
672
673template <typename K_TYPE, typename V_TYPE, typename ALLOC, typename Compare>
676
677template <typename K_TYPE, typename V_TYPE, typename ALLOC, typename Compare>
680{
681 if (this->size_ == 0){
682 return nullptr;
683 }
684
685 u_integer levels = this->getCurLevels();
686 auto cur_p = this->head_;
687 skipListNode* next_p;
688 for (u_integer i = levels; i > 0; --i) {
689 next_p = cur_p->getPNext(i);
690 while (next_p){
691 if (equal(key, next_p)){
692 return next_p;
693 }
694 if (this->highPriority(key, next_p)){
695 break;
696 }
697 cur_p = next_p;
698 next_p = next_p->getPNext(i);
699 }
700 }
701 return equal(key, next_p) ? next_p : nullptr;
702}
703
704template <typename K_TYPE, typename V_TYPE, typename ALLOC, typename Compare>
705bool original::skipList<K_TYPE, V_TYPE, ALLOC, Compare>::modify(const K_TYPE& key, const V_TYPE& value)
706{
707 auto cur_p = this->find(key);
708 if (!cur_p){
709 return false;
710 }
711
712 cur_p->setValue(value);
713 return true;
714}
715
716template <typename K_TYPE, typename V_TYPE, typename ALLOC, typename Compare>
717bool original::skipList<K_TYPE, V_TYPE, ALLOC, Compare>::insert(const K_TYPE& key, const V_TYPE& value)
718{
719 u_integer new_levels = this->getRandomLevels();
720 if (new_levels > this->getCurLevels()) {
721 this->expandCurLevels(new_levels);
722 }
723
724 vector<skipListNode*> update(new_levels, rebind_alloc_pointer{}, nullptr);
725 skipListNode* cur = this->head_;
726
727 for (u_integer i = this->getCurLevels(); i > 0; --i) {
728 while (cur->getPNext(i) && !this->highPriority(key, cur->getPNext(i))) {
729 cur = cur->getPNext(i);
730 }
731 if (i <= new_levels) {
732 update[i - 1] = cur;
733
734 if (equal(key, cur) && cur != this->head_) {
735 return false;
736 }
737 }
738 }
739
740 auto new_node = this->createNode(key, value, new_levels);
741 for (u_integer i = 0; i < new_levels; ++i) {
742 auto new_next = update[i]->getPNext(i + 1);
743 skipListNode::connect(i + 1, new_node, new_next);
744 skipListNode::connect(i + 1, update[i], new_node);
745 }
746
747 this->size_ += 1;
748 return true;
749}
750
751template <typename K_TYPE, typename V_TYPE, typename ALLOC, typename Compare>
753{
754 auto cur_p = this->find(key);
755 if (!cur_p){
756 return false;
757 }
758
759 auto cur_levels = cur_p->getLevels();
760 vector<skipListNode*> prev_nodes{cur_levels, rebind_alloc_pointer{}, this->head_};
761 vector<skipListNode*> next_nodes{cur_levels, rebind_alloc_pointer{}, nullptr};
762 for (u_integer i = 0; i < cur_levels; ++i) {
763 next_nodes[i] = cur_p->getPNext(i + 1);
764 while (true){
765 skipListNode* cur_node = prev_nodes[i];
766 skipListNode* next_node = cur_node->getPNext(i + 1);
767 if (!next_node || !this->highPriority(next_node, cur_p)){
768 break;
769 }
770 prev_nodes[i] = next_node;
771 }
772 }
773 for (u_integer i = 0; i < cur_levels; ++i) {
774 skipListNode::connect(i + 1, prev_nodes[i], next_nodes[i]);
775 }
776 this->destroyNode(cur_p);
777
778 u_integer decrement = 0;
779 for (u_integer i = this->getCurLevels(); i > 0; --i) {
780 if (this->head_->getPNext(i)){
781 break;
782 }
783 decrement += 1;
784 }
785 if (decrement > 0){
786 this->shrinkCurLevels(this->getCurLevels() - decrement);
787 }
788 this->size_ -= 1;
789 return true;
790}
791
792template <typename K_TYPE, typename V_TYPE, typename ALLOC, typename Compare>
794{
795 auto cur = this->head_;
796 while (cur) {
797 auto next = cur->getPNext(1);
798 this->destroyNode(cur);
799 cur = next;
800 }
801}
802
803template <typename K_TYPE, typename V_TYPE, typename ALLOC, typename Compare>
808
809#endif //SKIPLIST_H
Default memory allocator using allocators utilities.
Definition allocator.h:154
Container for two heterogeneous elements.
Definition couple.h:37
Comparator for increasing comparison (less than).
Definition comparator.h:63
Exception for container index out-of-range errors.
Definition error.h:84
Unique ownership smart pointer with move semantics.
Definition ownerPtr.h:30
Abstract base class for unique element containers.
Definition set.h:44
Forward iterator for skipList.
Definition skipList.h:164
Iterator & operator=(const Iterator &other)
Copy assignment operator.
Definition skipList.h:480
static integer ptrDistance(const Iterator *start, const Iterator *end)
Calculates distance between two iterators.
Definition skipList.h:555
integer operator-(const Iterator &other) const
Calculates distance between iterators.
Definition skipList.h:518
void operator+=(integer steps) const
Advances iterator by steps.
Definition skipList.h:506
couple< const K_TYPE, V_TYPE > & get()
Gets current element (non-const)
Definition skipList.h:530
skipListNode * cur_
Current node pointer.
Definition skipList.h:166
Iterator(skipListNode *cur=nullptr)
Constructs iterator.
Definition skipList.h:470
void next() const
Moves to next element.
Definition skipList.h:495
bool isValid() const
Checks if iterator is valid.
Definition skipList.h:549
Iterator * clone() const
Creates a copy of this iterator.
Definition skipList.h:501
bool hasNext() const
Checks if more elements exist forward.
Definition skipList.h:490
Internal node class for Skip List.
Definition skipList.h:54
void expandLevels(u_integer new_levels)
Expands node to more levels.
Definition skipList.h:423
void setPNext(u_integer levels, skipListNode *next)
Sets next node at specified level.
Definition skipList.h:456
void shrinkLevels(u_integer new_levels)
Shrinks node to fewer levels.
Definition skipList.h:434
static void connect(u_integer levels, skipListNode *prev, skipListNode *next)
Connects two nodes at specified level.
Definition skipList.h:462
u_integer getLevels() const
Gets number of levels for this node.
Definition skipList.h:418
const V_TYPE & getValue() const
Gets value (const)
Definition skipList.h:407
couple< const K_TYPE, V_TYPE > & getVal()
Gets key-value pair (non-const)
Definition skipList.h:389
const K_TYPE & getKey() const
Gets key.
Definition skipList.h:401
skipListNode(const K_TYPE &key=K_TYPE{}, const V_TYPE &value=V_TYPE{}, u_integer levels=1, std::initializer_list< skipListNode * > next={})
Constructs a new skipListNode.
Definition skipList.h:374
void setValue(const V_TYPE &value)
Sets new value.
Definition skipList.h:445
skipListNode * getPNext(u_integer levels) const
Gets next node at specified level.
Definition skipList.h:451
rebind_alloc_node rebind_alloc
Node allocator.
Definition skipList.h:155
skipListNode * findLastNode() const
Finds last node in list.
Definition skipList.h:665
void listDestroy() noexcept
Destroys entire list and deallocates all nodes.
Definition skipList.h:793
skipListNode * head_
Definition skipList.h:153
skipListNode * listCopy() const
Creates a deep copy of the list.
Definition skipList.h:644
u_integer getCurLevels() const
Gets current number of levels in list.
Definition skipList.h:628
bool insert(const K_TYPE &key, const V_TYPE &value)
Inserts new key-value pair.
Definition skipList.h:717
skipListNode * createNode(const K_TYPE &key=K_TYPE{}, const V_TYPE &value=V_TYPE{}, u_integer levels=1, std::initializer_list< skipListNode * > next={}) const
Creates a new node with given parameters.
Definition skipList.h:574
void expandCurLevels(u_integer new_levels)
Expands list to more levels.
Definition skipList.h:633
void shrinkCurLevels(u_integer new_levels)
Shrinks list to fewer levels.
Definition skipList.h:638
skipListNode * find(const K_TYPE &key) const
Finds node with given key.
Definition skipList.h:679
std::uniform_real_distribution< floating > dis_
Definition skipList.h:157
bool modify(const K_TYPE &key, const V_TYPE &value)
Modifies value for existing key.
Definition skipList.h:705
static bool equal(const K_TYPE &key, skipListNode *next)
Checks if key matches node's key.
Definition skipList.h:606
typename ALLOC::template rebind_alloc< skipListNode * > rebind_alloc_pointer
Definition skipList.h:150
bool highPriority(const K_TYPE &key, skipListNode *next) const
Compares priority between a key and a node.
Definition skipList.h:597
bool highPriority(skipListNode *cur, skipListNode *next) const
Compares priority between two nodes.
Definition skipList.h:588
~skipList()
Destructor.
Definition skipList.h:804
void destroyNode(skipListNode *node) const
Destroys a node and deallocates memory.
Definition skipList.h:582
u_integer getRandomLevels()
Generates random number of levels for new node.
Definition skipList.h:616
bool erase(const K_TYPE &key)
Erases node with given key.
Definition skipList.h:752
skipList(Compare compare=Compare{})
Constructs skipList with given comparison function.
Definition skipList.h:674
typename ALLOC::template rebind_alloc< skipListNode > rebind_alloc_node
Definition skipList.h:149
Exception for unimplemented method calls.
Definition error.h:123
Dynamic array container with amortized constant time operations.
Definition vector.h:43
u_integer size() const override
Gets the size of the vector.
Definition vector.h:640
void pushEnd(const TYPE &e) override
Inserts an element at the end of the vector.
Definition vector.h:739
TYPE popEnd() override
Removes and returns the last element in the vector.
Definition vector.h:790
Comparator base class and concrete comparator classes.
Combines Comparable and CallbackOf for comparison callbacks.
Definition types.h:92
Generic pair container implementation.
Main namespace for the project Original.
Definition algorithms.h:21
std::uint32_t u_integer
32-bit unsigned integer type for sizes and indexes
Definition config.h:43
double floating
Double-precision floating-point type.
Definition config.h:51
std::int64_t integer
64-bit signed integer type for arithmetic operations
Definition config.h:35
Dynamic array container with automatic resizing.