|
@@ -28,16 +28,22 @@
|
|
|
|
|
|
|
|
#include <new>
|
|
#include <new>
|
|
|
|
|
|
|
|
-// Based on http://eternallyconfuzzled.com/tuts/datastructures/jsw_tut_skip.aspx
|
|
|
|
|
|
|
+// Based on http://eternallyconfuzzled.com/tuts/datastructures/jsw_tut_rbtree.aspx
|
|
|
|
|
|
|
|
-/// Map template class using a skip list
|
|
|
|
|
-template <class T, class U> class Map : public SkipListBase
|
|
|
|
|
|
|
+/// Map template class using a red-black tree
|
|
|
|
|
+template <class T, class U> class Map : public TreeBase
|
|
|
{
|
|
{
|
|
|
public:
|
|
public:
|
|
|
/// Map key-value pair with const key
|
|
/// Map key-value pair with const key
|
|
|
class KeyValue
|
|
class KeyValue
|
|
|
{
|
|
{
|
|
|
public:
|
|
public:
|
|
|
|
|
+ /// Construct with default key
|
|
|
|
|
+ KeyValue() :
|
|
|
|
|
+ first_(T())
|
|
|
|
|
+ {
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
/// Construct with key
|
|
/// Construct with key
|
|
|
KeyValue(const T& first) :
|
|
KeyValue(const T& first) :
|
|
|
first_(first)
|
|
first_(first)
|
|
@@ -61,31 +67,41 @@ public:
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
/// Map node
|
|
/// Map node
|
|
|
- struct Node : public SkipListNodeBase
|
|
|
|
|
|
|
+ struct Node : public TreeNodeBase
|
|
|
{
|
|
{
|
|
|
- /// Key-value pair
|
|
|
|
|
- KeyValue pair_;
|
|
|
|
|
|
|
+ // Construct undefined
|
|
|
|
|
+ Node()
|
|
|
|
|
+ {
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- /// Return next node on a specific height
|
|
|
|
|
- Node* GetNext(unsigned height) const
|
|
|
|
|
|
|
+ // Construct with key
|
|
|
|
|
+ Node(const T& key) :
|
|
|
|
|
+ pair_(key)
|
|
|
{
|
|
{
|
|
|
- if (!height)
|
|
|
|
|
- return static_cast<Node*>(next_);
|
|
|
|
|
- else
|
|
|
|
|
- return static_cast<Node*>(levels_[height - 1]);
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- /// Return previous node
|
|
|
|
|
- Node* GetPrev() { return static_cast<Node*>(prev_); }
|
|
|
|
|
|
|
+ // Construct with key and value
|
|
|
|
|
+ Node(const T& key, const U& value) :
|
|
|
|
|
+ pair_(key, value)
|
|
|
|
|
+ {
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /// Key-value pair
|
|
|
|
|
+ KeyValue pair_;
|
|
|
|
|
+
|
|
|
|
|
+ /// Return parent node
|
|
|
|
|
+ Node* GetParent() const { return static_cast<Node*>(parent_); }
|
|
|
|
|
+ /// Return the left or right child
|
|
|
|
|
+ Node* GetChild(unsigned dir) const { return static_cast<Node*>(link_[dir]); }
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
/// Map node iterator
|
|
/// Map node iterator
|
|
|
- class Iterator : public ListIteratorBase
|
|
|
|
|
|
|
+ class Iterator : public TreeIteratorBase
|
|
|
{
|
|
{
|
|
|
public:
|
|
public:
|
|
|
- /// Construct
|
|
|
|
|
- explicit Iterator(Node* ptr) :
|
|
|
|
|
- ListIteratorBase(ptr)
|
|
|
|
|
|
|
+ // Construct
|
|
|
|
|
+ Iterator(Node* ptr) :
|
|
|
|
|
+ TreeIteratorBase(ptr)
|
|
|
{
|
|
{
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -105,18 +121,18 @@ public:
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
/// Set node const iterator
|
|
/// Set node const iterator
|
|
|
- class ConstIterator : public ListIteratorBase
|
|
|
|
|
|
|
+ class ConstIterator : public TreeIteratorBase
|
|
|
{
|
|
{
|
|
|
public:
|
|
public:
|
|
|
- /// Construct
|
|
|
|
|
- explicit ConstIterator(Node* ptr) :
|
|
|
|
|
- ListIteratorBase(ptr)
|
|
|
|
|
|
|
+ // Construct
|
|
|
|
|
+ ConstIterator(Node* ptr) :
|
|
|
|
|
+ TreeIteratorBase(ptr)
|
|
|
{
|
|
{
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- /// Construct from a non-const iterator
|
|
|
|
|
- ConstIterator(const Iterator& rhs) :
|
|
|
|
|
- ListIteratorBase(rhs.ptr_)
|
|
|
|
|
|
|
+ // Construct from a non-const iterator
|
|
|
|
|
+ ConstIterator(const Iterator& it) :
|
|
|
|
|
+ TreeIteratorBase(it.ptr_)
|
|
|
{
|
|
{
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -125,11 +141,11 @@ public:
|
|
|
/// Preincrement the pointer
|
|
/// Preincrement the pointer
|
|
|
ConstIterator& operator ++ () { GotoNext(); return *this; }
|
|
ConstIterator& operator ++ () { GotoNext(); return *this; }
|
|
|
/// Postincrement the pointer
|
|
/// Postincrement the pointer
|
|
|
- ConstIterator operator ++ (int) { Iterator it = *this; GotoNext(); return it; }
|
|
|
|
|
|
|
+ ConstIterator operator ++ (int) { ConstIterator it = *this; GotoNext(); return it; }
|
|
|
/// Predecrement the pointer
|
|
/// Predecrement the pointer
|
|
|
ConstIterator& operator -- () { GotoPrev(); return *this; }
|
|
ConstIterator& operator -- () { GotoPrev(); return *this; }
|
|
|
/// Postdecrement the pointer
|
|
/// Postdecrement the pointer
|
|
|
- ConstIterator operator -- (int) { Iterator it = *this; GotoPrev(); return it; }
|
|
|
|
|
|
|
+ ConstIterator operator -- (int) { ConstIterator it = *this; GotoPrev(); return it; }
|
|
|
|
|
|
|
|
/// Point to the pair
|
|
/// Point to the pair
|
|
|
const KeyValue* operator -> () const { return &(static_cast<Node*>(ptr_))->pair_; }
|
|
const KeyValue* operator -> () const { return &(static_cast<Node*>(ptr_))->pair_; }
|
|
@@ -137,96 +153,39 @@ public:
|
|
|
const KeyValue& operator * () const { return (static_cast<Node*>(ptr_))->pair_; }
|
|
const KeyValue& operator * () const { return (static_cast<Node*>(ptr_))->pair_; }
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- /// Construct empty
|
|
|
|
|
- Map(unsigned maxHeight = MAX_HEIGHT) :
|
|
|
|
|
- SkipListBase(maxHeight)
|
|
|
|
|
|
|
+ /// Construct empty map
|
|
|
|
|
+ Map()
|
|
|
{
|
|
{
|
|
|
- // Allocate the head and tail nodes and zero the next pointers
|
|
|
|
|
- head_ = AllocateNode(maxHeight_);
|
|
|
|
|
- tail_ = AllocateNode(maxHeight_);
|
|
|
|
|
- Node* head = GetHead();
|
|
|
|
|
- Node* tail = GetTail();
|
|
|
|
|
- for (unsigned i = 0; i < maxHeight_; ++i)
|
|
|
|
|
- {
|
|
|
|
|
- head->SetNext(i, tail);
|
|
|
|
|
- tail->SetNext(i, 0);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // Allocate the fixup pointers
|
|
|
|
|
- fix_ = reinterpret_cast<void**>(new Node*[maxHeight_]);
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- /// Construct from another map
|
|
|
|
|
- Map(const Map<T, U>& map) :
|
|
|
|
|
- SkipListBase(map.maxHeight_)
|
|
|
|
|
|
|
+ /// Construct with another map
|
|
|
|
|
+ Map(const Map<T, U>& map)
|
|
|
{
|
|
{
|
|
|
- // Allocate the head and tail nodes and zero the next pointers
|
|
|
|
|
- head_ = AllocateNode(maxHeight_);
|
|
|
|
|
- tail_ = AllocateNode(maxHeight_);
|
|
|
|
|
- Node* head = GetHead();
|
|
|
|
|
- Node* tail = GetTail();
|
|
|
|
|
- for (unsigned i = 0; i < maxHeight_; ++i)
|
|
|
|
|
- {
|
|
|
|
|
- head->SetNext(i, tail);
|
|
|
|
|
- tail->SetNext(i, 0);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // Allocate the fixup pointers
|
|
|
|
|
- fix_ = reinterpret_cast<void**>(new Node*[maxHeight_]);
|
|
|
|
|
-
|
|
|
|
|
- // Then assign the other map
|
|
|
|
|
*this = map;
|
|
*this = map;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- /// Destruct
|
|
|
|
|
|
|
+ /// Destruct the set
|
|
|
~Map()
|
|
~Map()
|
|
|
{
|
|
{
|
|
|
Clear();
|
|
Clear();
|
|
|
- DeleteNode(GetHead());
|
|
|
|
|
- DeleteNode(GetTail());
|
|
|
|
|
- delete[] GetFix();
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- /// Assign from another map
|
|
|
|
|
- Map& operator = (const Map<T, U>& rhs)
|
|
|
|
|
|
|
+ /// Assign a map
|
|
|
|
|
+ Map<T, U>& operator = (const Map<T, U>& map)
|
|
|
{
|
|
{
|
|
|
Clear();
|
|
Clear();
|
|
|
-
|
|
|
|
|
- // Insert the nodes with same heights
|
|
|
|
|
- for (Node* i = rhs.GetHead()->GetNext(0); i != rhs.GetTail(); i = i->GetNext(0))
|
|
|
|
|
- InsertNode(Pair<T, U>(i->pair_.first_, i->pair_.second_), i->height_);
|
|
|
|
|
|
|
+ Insert(map.Begin(), map.End());
|
|
|
|
|
|
|
|
return *this;
|
|
return *this;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- /// Add-assign a pair
|
|
|
|
|
|
|
+ /// Add-assign a value
|
|
|
Map& operator += (const Pair<T, U>& rhs)
|
|
Map& operator += (const Pair<T, U>& rhs)
|
|
|
{
|
|
{
|
|
|
Insert(rhs);
|
|
Insert(rhs);
|
|
|
return *this;
|
|
return *this;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- /// Add-assign a map
|
|
|
|
|
- Map& operator += (const Map<T, U>& rhs)
|
|
|
|
|
- {
|
|
|
|
|
- Insert(rhs.Begin(), rhs.End());
|
|
|
|
|
- return *this;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /// Index the map
|
|
|
|
|
- U& operator [] (const T& key)
|
|
|
|
|
- {
|
|
|
|
|
- Node* node = FindNode(key);
|
|
|
|
|
- if (node)
|
|
|
|
|
- return node->pair_.second_;
|
|
|
|
|
- else
|
|
|
|
|
- {
|
|
|
|
|
- // If node did not exist, insert a node with default value, then return the value
|
|
|
|
|
- node = InsertNode(Pair<T, U>(key, U()), 0);
|
|
|
|
|
- return node->pair_.second_;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
/// Test for equality with another map
|
|
/// Test for equality with another map
|
|
|
bool operator == (const Map<T, U>& rhs) const
|
|
bool operator == (const Map<T, U>& rhs) const
|
|
|
{
|
|
{
|
|
@@ -265,278 +224,305 @@ public:
|
|
|
return false;
|
|
return false;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- /// Insert into the map
|
|
|
|
|
- void Insert(const T& key, const U& value)
|
|
|
|
|
|
|
+ /// Add-assign a map
|
|
|
|
|
+ Map<T, U>& operator += (const Map<T, U>& rhs)
|
|
|
|
|
+ {
|
|
|
|
|
+ Insert(rhs.Begin(), rhs.End());
|
|
|
|
|
+ return *this;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /// Clear the map
|
|
|
|
|
+ void Clear()
|
|
|
|
|
+ {
|
|
|
|
|
+ Node* root = GetRoot();
|
|
|
|
|
+ if (!root)
|
|
|
|
|
+ return;
|
|
|
|
|
+ EraseNodes(root);
|
|
|
|
|
+ root_ = 0;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /// Insert a pair and return iterator to it
|
|
|
|
|
+ Iterator Insert(const Pair<T, U>& pair)
|
|
|
|
|
+ {
|
|
|
|
|
+ return Iterator(InsertNode(pair.first_, pair.second_));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /// Insert a map
|
|
|
|
|
+ void Insert(const Map<T, U>& map)
|
|
|
{
|
|
{
|
|
|
- InsertNode(MakePair(key, value), 0);
|
|
|
|
|
|
|
+ Insert(map.Begin(), map.End());
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- /// Insert into the map
|
|
|
|
|
- void Insert(const Pair<T, U>& pair)
|
|
|
|
|
|
|
+ /// Insert a key by iterator. Return iterator to the value
|
|
|
|
|
+ Iterator Insert(const ConstIterator& it)
|
|
|
{
|
|
{
|
|
|
- InsertNode(pair, 0);
|
|
|
|
|
|
|
+ return Iterator(InsertNode(it->first_, it->second_));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- /// Insert a range by iterators
|
|
|
|
|
- void Insert(const Iterator& start, const Iterator& end)
|
|
|
|
|
|
|
+ /// Insert by a range of iterators
|
|
|
|
|
+ void Insert(const ConstIterator& begin, const ConstIterator& end)
|
|
|
{
|
|
{
|
|
|
- Iterator it = start;
|
|
|
|
|
|
|
+ ConstIterator it = begin;
|
|
|
while (it != end)
|
|
while (it != end)
|
|
|
{
|
|
{
|
|
|
- Iterator current = it++;
|
|
|
|
|
- Insert(*current);
|
|
|
|
|
- // Break if the iterator got stuck
|
|
|
|
|
- if (it == current)
|
|
|
|
|
- break;
|
|
|
|
|
|
|
+ InsertNode(it->first_, it->second_);
|
|
|
|
|
+ ++it;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- /// Erase a key from the map. Return true if was found and erased
|
|
|
|
|
|
|
+ /// Erase a key. Return true if was found
|
|
|
bool Erase(const T& key)
|
|
bool Erase(const T& key)
|
|
|
{
|
|
{
|
|
|
- Node* head = GetHead();
|
|
|
|
|
- Node* tail = GetTail();
|
|
|
|
|
- Node** fix = GetFix();
|
|
|
|
|
- Node* i = head;
|
|
|
|
|
-
|
|
|
|
|
- for (unsigned j = height_ - 1; j < MAX_HEIGHT; --j)
|
|
|
|
|
- {
|
|
|
|
|
- for (;;)
|
|
|
|
|
- {
|
|
|
|
|
- Node* next = i->GetNext(j);
|
|
|
|
|
- if ((next) && (next != tail) && (key > next->pair_.first_))
|
|
|
|
|
- i = next;
|
|
|
|
|
- else
|
|
|
|
|
- break;
|
|
|
|
|
- }
|
|
|
|
|
- fix_[j] = i;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // Check if key does not exist
|
|
|
|
|
- Node* toRemove = i->GetNext(0);
|
|
|
|
|
- if ((!toRemove) || (toRemove == tail) || (toRemove->pair_.first_ != key))
|
|
|
|
|
- return false;
|
|
|
|
|
-
|
|
|
|
|
- // Fix the previous link. However, do not set the head node as a previous link
|
|
|
|
|
- Node* prev = toRemove->GetPrev();
|
|
|
|
|
- Node* next = toRemove->GetNext(0);
|
|
|
|
|
- if (next)
|
|
|
|
|
- next->SetPrev(prev != head ? prev : 0);
|
|
|
|
|
-
|
|
|
|
|
- // Fix the next links
|
|
|
|
|
- for (unsigned j = 0; j < height_; ++j)
|
|
|
|
|
- {
|
|
|
|
|
- Node* fixNext = fix[j]->GetNext(j);
|
|
|
|
|
- if (fixNext)
|
|
|
|
|
- fix[j]->SetNext(j, fixNext->GetNext(j));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // Check if height should be changed
|
|
|
|
|
- while (height_ > 0)
|
|
|
|
|
- {
|
|
|
|
|
- if (head->GetNext(height_ - 1))
|
|
|
|
|
- break;
|
|
|
|
|
- head->SetNext(--height_, 0);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- DeleteNode(toRemove);
|
|
|
|
|
- --size_;
|
|
|
|
|
- return true;
|
|
|
|
|
|
|
+ return EraseNode(key);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- /// Erase by an iterator. Return an iterator to the next element
|
|
|
|
|
- Iterator Erase(Iterator it)
|
|
|
|
|
|
|
+ /// Erase a key by iterator. Return true if was found
|
|
|
|
|
+ bool Erase(const Iterator& it)
|
|
|
{
|
|
{
|
|
|
- if (it != End())
|
|
|
|
|
- {
|
|
|
|
|
- Iterator current = it++;
|
|
|
|
|
- Erase(current->first_);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- return it;
|
|
|
|
|
|
|
+ return EraseNode(it->first_);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- /// Erase by a range of iterators. Return the end iterator
|
|
|
|
|
- Iterator Erase(const Iterator& start, const Iterator& end)
|
|
|
|
|
|
|
+ /// Return whether contains a key
|
|
|
|
|
+ bool Contains(const T& key)
|
|
|
{
|
|
{
|
|
|
- Iterator it = start;
|
|
|
|
|
- while (it != end)
|
|
|
|
|
- {
|
|
|
|
|
- Iterator current = it++;
|
|
|
|
|
- // Break if the iterator got stuck
|
|
|
|
|
- if (it == current)
|
|
|
|
|
- break;
|
|
|
|
|
- Erase(current->first_);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- return it;
|
|
|
|
|
|
|
+ return FindNode(key) != 0;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- /// Clear the map
|
|
|
|
|
- void Clear()
|
|
|
|
|
|
|
+ /// Index the map. Create new node if key not found
|
|
|
|
|
+ U& operator [] (const T& key)
|
|
|
{
|
|
{
|
|
|
- // Let the head and tails node remain, but reset the next pointers
|
|
|
|
|
- Node* head = GetHead();
|
|
|
|
|
- Node* tail = GetTail();
|
|
|
|
|
- Node* node = head->GetNext(0);
|
|
|
|
|
-
|
|
|
|
|
- for (unsigned i = 0; i < maxHeight_; ++i)
|
|
|
|
|
- {
|
|
|
|
|
- head->SetNext(i, tail);
|
|
|
|
|
- tail->SetPrev(0);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // Then remove all the key nodes
|
|
|
|
|
- while (node != tail_)
|
|
|
|
|
|
|
+ Node* node = FindNode(key);
|
|
|
|
|
+ if (node)
|
|
|
|
|
+ return node->pair_.second_;
|
|
|
|
|
+ else
|
|
|
{
|
|
{
|
|
|
- Node* current = node;
|
|
|
|
|
- node = node->GetNext(0);
|
|
|
|
|
- DeleteNode(current);
|
|
|
|
|
|
|
+ node = InsertNode(key, U());
|
|
|
|
|
+ return node->pair_.second_;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- height_ = 0;
|
|
|
|
|
- size_ = 0;
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/// Return iterator to the node with key, or end iterator if not found
|
|
/// Return iterator to the node with key, or end iterator if not found
|
|
|
Iterator Find(const T& key) { Node* node = FindNode(key); return node ? Iterator(node) : End(); }
|
|
Iterator Find(const T& key) { Node* node = FindNode(key); return node ? Iterator(node) : End(); }
|
|
|
/// Return const iterator to the node with key, or null iterator if not found
|
|
/// Return const iterator to the node with key, or null iterator if not found
|
|
|
ConstIterator Find(const T& key) const { Node* node = FindNode(key); return node ? ConstIterator(node) : End(); }
|
|
ConstIterator Find(const T& key) const { Node* node = FindNode(key); return node ? ConstIterator(node) : End(); }
|
|
|
- /// Return iterator to the first actual node
|
|
|
|
|
- Iterator Begin() { return Iterator(GetHead()->GetNext(0)); }
|
|
|
|
|
- /// Return iterator to the first actual node
|
|
|
|
|
- ConstIterator Begin() const { return ConstIterator(GetHead()->GetNext(0)); }
|
|
|
|
|
- /// Return iterator to the end
|
|
|
|
|
- Iterator End() { return Iterator(GetTail()); }
|
|
|
|
|
|
|
+ /// Return iterator to the beginning
|
|
|
|
|
+ Iterator Begin() { return Iterator(FindFirst()); }
|
|
|
|
|
+ /// Return const iterator to the beginning
|
|
|
|
|
+ ConstIterator Begin() const { return ConstIterator(FindFirst()); }
|
|
|
/// Return iterator to the end
|
|
/// Return iterator to the end
|
|
|
- ConstIterator End() const { return ConstIterator(GetTail()); }
|
|
|
|
|
- /// Return first pair
|
|
|
|
|
- KeyValue& Front() { return *Begin(); }
|
|
|
|
|
- /// Return const first pair
|
|
|
|
|
- const KeyValue& Front() const { return *Begin(); }
|
|
|
|
|
- /// Return last pair
|
|
|
|
|
- const KeyValue& Back() { return *(--End()); }
|
|
|
|
|
- /// Return const last pair
|
|
|
|
|
- const KeyValue& Back() const { return *(--End()); }
|
|
|
|
|
-
|
|
|
|
|
- /// Return whether contains a key
|
|
|
|
|
- bool Contains(const T& key) const { return FindNode(key) != 0; }
|
|
|
|
|
|
|
+ Iterator End() { return ++Iterator(FindLast()); }
|
|
|
|
|
+ /// Return const iterator to the end
|
|
|
|
|
+ ConstIterator End() const { return ++ConstIterator(FindLast()); }
|
|
|
|
|
+ /// Return first key
|
|
|
|
|
+ const T& Front() { return FindFirst()->key_; }
|
|
|
|
|
+ /// Return last key
|
|
|
|
|
+ const T& Back() { return FindLast()->key_; }
|
|
|
/// Return number of keys
|
|
/// Return number of keys
|
|
|
unsigned Size() const { return size_; }
|
|
unsigned Size() const { return size_; }
|
|
|
- /// Return current height
|
|
|
|
|
- unsigned Height() const { return height_; }
|
|
|
|
|
- /// Return whether map is empty
|
|
|
|
|
|
|
+ /// Return whether the set is empty
|
|
|
bool Empty() const { return size_ == 0; }
|
|
bool Empty() const { return size_ == 0; }
|
|
|
|
|
|
|
|
private:
|
|
private:
|
|
|
- /// Return the head pointer with correct type
|
|
|
|
|
- Node* GetHead() const { return reinterpret_cast<Node*>(head_); }
|
|
|
|
|
- /// Return the tail pointer with correct type
|
|
|
|
|
- Node* GetTail() const { return reinterpret_cast<Node*>(tail_); }
|
|
|
|
|
- /// Return the fixup array with correct type
|
|
|
|
|
- Node** GetFix() const { return reinterpret_cast<Node**>(fix_); }
|
|
|
|
|
|
|
+ /// Return the root pointer with correct type
|
|
|
|
|
+ Node* GetRoot() const { return reinterpret_cast<Node*>(root_); }
|
|
|
|
|
|
|
|
- /// Find a key from the map. Return null if not found
|
|
|
|
|
|
|
+ /// Find the node with smallest key
|
|
|
|
|
+ Node* FindFirst() const
|
|
|
|
|
+ {
|
|
|
|
|
+ Node* node = GetRoot();
|
|
|
|
|
+ while ((node) && (node->link_[0]))
|
|
|
|
|
+ node = node->GetChild(0);
|
|
|
|
|
+ return node;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /// Find the node with largest key
|
|
|
|
|
+ Node* FindLast() const
|
|
|
|
|
+ {
|
|
|
|
|
+ Node* node = GetRoot();
|
|
|
|
|
+ while ((node) && (node->link_[1]))
|
|
|
|
|
+ node = node->GetChild(1);
|
|
|
|
|
+ return node;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /// Find a node with key. Return null if not found
|
|
|
Node* FindNode(const T& key) const
|
|
Node* FindNode(const T& key) const
|
|
|
{
|
|
{
|
|
|
- Node* i = GetHead();
|
|
|
|
|
- Node* tail = GetTail();
|
|
|
|
|
|
|
+ Node* node = GetRoot();
|
|
|
|
|
+ while (node)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (node->pair_.first_ == key)
|
|
|
|
|
+ return node;
|
|
|
|
|
+ else
|
|
|
|
|
+ node = node->GetChild(node->pair_.first_ < key);
|
|
|
|
|
+ }
|
|
|
|
|
+ return 0;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /// Insert a node and return pointer to it
|
|
|
|
|
+ Node* InsertNode(const T& key, const U& value)
|
|
|
|
|
+ {
|
|
|
|
|
+ Node* ret = 0;
|
|
|
|
|
|
|
|
- for (unsigned j = height_ - 1; j < MAX_HEIGHT; --j)
|
|
|
|
|
|
|
+ if (!root_)
|
|
|
{
|
|
{
|
|
|
|
|
+ root_ = ret = new Node(key, value);
|
|
|
|
|
+ ++size_;
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ Node head;
|
|
|
|
|
+ Node* g, * t, * p, * q;
|
|
|
|
|
+
|
|
|
|
|
+ unsigned dir = 0;
|
|
|
|
|
+ unsigned last;
|
|
|
|
|
+
|
|
|
|
|
+ t = &head;
|
|
|
|
|
+ g = p = 0;
|
|
|
|
|
+ q = GetRoot();
|
|
|
|
|
+ t->SetChild(1, GetRoot());
|
|
|
|
|
+
|
|
|
for (;;)
|
|
for (;;)
|
|
|
{
|
|
{
|
|
|
- Node* next = i->GetNext(j);
|
|
|
|
|
- if ((next) && (next != tail) && (key > next->pair_.first_))
|
|
|
|
|
- i = next;
|
|
|
|
|
- else
|
|
|
|
|
|
|
+ if (!q)
|
|
|
|
|
+ {
|
|
|
|
|
+ p->SetChild(dir, q = ret = new Node(key, value));
|
|
|
|
|
+ ++size_;
|
|
|
|
|
+ }
|
|
|
|
|
+ else if ((isRed(q->link_[0])) && (isRed(q->link_[1])))
|
|
|
|
|
+ {
|
|
|
|
|
+ q->isRed_ = true;
|
|
|
|
|
+ q->link_[0]->isRed_ = false;
|
|
|
|
|
+ q->link_[1]->isRed_ = false;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if ((isRed(q)) && (isRed(p)))
|
|
|
|
|
+ {
|
|
|
|
|
+ unsigned dir2 = (t->link_[1] == g);
|
|
|
|
|
+ if (q == p->link_[last])
|
|
|
|
|
+ t->SetChild(dir2, RotateSingle(g, !last));
|
|
|
|
|
+ else
|
|
|
|
|
+ t->SetChild(dir2, RotateDouble(g, !last));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (q->pair_.first_ == key)
|
|
|
|
|
+ {
|
|
|
|
|
+ ret = q;
|
|
|
|
|
+ ret->pair_.second_ = value;
|
|
|
break;
|
|
break;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ last = dir;
|
|
|
|
|
+ dir = q->pair_.first_ < key;
|
|
|
|
|
+
|
|
|
|
|
+ if (g)
|
|
|
|
|
+ t = g;
|
|
|
|
|
+ g = p;
|
|
|
|
|
+ p = q;
|
|
|
|
|
+ q = q->GetChild(dir);
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ root_ = head.GetChild(1);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- Node* next = i->GetNext(0);
|
|
|
|
|
- if ((next) && (next != tail) && (next->pair_.first_ == key))
|
|
|
|
|
- return next;
|
|
|
|
|
- else
|
|
|
|
|
- return 0;
|
|
|
|
|
|
|
+ root_->isRed_ = false;
|
|
|
|
|
+ root_->parent_ = 0;
|
|
|
|
|
+
|
|
|
|
|
+ return ret;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- /// Insert into the map with a specific height. Zero height will randomize. Return the node
|
|
|
|
|
- Node* InsertNode(const Pair<T, U>& pair, unsigned height)
|
|
|
|
|
|
|
+ /// Erase a node. Return true if was erased
|
|
|
|
|
+ bool EraseNode(const T& key)
|
|
|
{
|
|
{
|
|
|
- Node* head = GetHead();
|
|
|
|
|
- Node* tail = GetTail();
|
|
|
|
|
- Node** fix = GetFix();
|
|
|
|
|
- Node* i = head;
|
|
|
|
|
|
|
+ if (!root_)
|
|
|
|
|
+ return false;
|
|
|
|
|
+
|
|
|
|
|
+ Node head;
|
|
|
|
|
+ Node* q, * p, *g;
|
|
|
|
|
+ Node* f = 0;
|
|
|
|
|
+ unsigned dir = 1;
|
|
|
|
|
+ bool removed = false;
|
|
|
|
|
+
|
|
|
|
|
+ q = &head;
|
|
|
|
|
+ g = p = 0;
|
|
|
|
|
+ q->SetChild(1, GetRoot());
|
|
|
|
|
|
|
|
- for (unsigned j = height_ - 1; j < MAX_HEIGHT; --j)
|
|
|
|
|
|
|
+ while (q->link_[dir])
|
|
|
{
|
|
{
|
|
|
- for (;;)
|
|
|
|
|
|
|
+ unsigned last = dir;
|
|
|
|
|
+ g = p;
|
|
|
|
|
+ p = q;
|
|
|
|
|
+ q = q->GetChild(dir);
|
|
|
|
|
+ dir = q->pair_.first_ < key;
|
|
|
|
|
+
|
|
|
|
|
+ if (q->pair_.first_ == key)
|
|
|
|
|
+ f = q;
|
|
|
|
|
+
|
|
|
|
|
+ if ((!isRed(q)) && (!isRed(q->GetChild(dir))))
|
|
|
{
|
|
{
|
|
|
- Node* next = i->GetNext(j);
|
|
|
|
|
- if ((next) && (next != tail) && (pair.first_ > next->pair_.first_))
|
|
|
|
|
- i = next;
|
|
|
|
|
- else
|
|
|
|
|
- break;
|
|
|
|
|
|
|
+ if (isRed(q->GetChild(!dir)))
|
|
|
|
|
+ {
|
|
|
|
|
+ p->SetChild(last, RotateSingle(q, dir));
|
|
|
|
|
+ p = p->GetChild(last);
|
|
|
|
|
+ }
|
|
|
|
|
+ else if (!isRed(q->GetChild(!dir)))
|
|
|
|
|
+ {
|
|
|
|
|
+ Node* s = p->GetChild(!last);
|
|
|
|
|
+
|
|
|
|
|
+ if (s)
|
|
|
|
|
+ {
|
|
|
|
|
+ if ((!isRed(s->GetChild(!last))) && (!isRed(s->GetChild(last))))
|
|
|
|
|
+ {
|
|
|
|
|
+ p->isRed_ = false;
|
|
|
|
|
+ s->isRed_ = true;
|
|
|
|
|
+ q->isRed_ = true;
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ int dir2 = (g->GetChild(1) == p);
|
|
|
|
|
+ if (isRed(s->GetChild(last)))
|
|
|
|
|
+ g->SetChild(dir2, RotateDouble(p, last));
|
|
|
|
|
+ else if (isRed(s->GetChild(!last)))
|
|
|
|
|
+ g->SetChild(dir2, RotateSingle(p, last));
|
|
|
|
|
+ q->isRed_ = g->GetChild(dir2)->isRed_ = true;
|
|
|
|
|
+ g->GetChild(dir2)->GetChild(0)->isRed_ = false;
|
|
|
|
|
+ g->GetChild(dir2)->GetChild(1)->isRed_ = false;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
- fix[j] = i;
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // Check if key already exists, in that case only modify the value
|
|
|
|
|
- Node* next = i->GetNext(0);
|
|
|
|
|
- if ((next) && (next != tail) && (next->pair_.first_ == pair.first_))
|
|
|
|
|
|
|
+ if (f)
|
|
|
{
|
|
{
|
|
|
- next->pair_.second_ = pair.second_;
|
|
|
|
|
- return next;
|
|
|
|
|
|
|
+ const_cast<T&>(f->pair_.first_) = q->pair_.first_;
|
|
|
|
|
+ f->pair_.second_ = q->pair_.second_;
|
|
|
|
|
+ p->SetChild(p->GetChild(1) == q, q->link_[q->GetChild(0) == 0]);
|
|
|
|
|
+ delete q;
|
|
|
|
|
+ --size_;
|
|
|
|
|
+ removed = true;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // Create new node, assign height and key
|
|
|
|
|
- if (!height)
|
|
|
|
|
- height = GetHeight();
|
|
|
|
|
- Node* newNode = AllocateNode(height, pair.first_);
|
|
|
|
|
- newNode->pair_.second_ = pair.second_;
|
|
|
|
|
-
|
|
|
|
|
- // Fix the previous link, however do not set the head node as previous
|
|
|
|
|
- if (i != head)
|
|
|
|
|
- newNode->SetPrev(i);
|
|
|
|
|
- if (next)
|
|
|
|
|
- next->SetPrev(newNode);
|
|
|
|
|
-
|
|
|
|
|
- while (newNode->height_ > height_)
|
|
|
|
|
- fix[height_++] = head;
|
|
|
|
|
-
|
|
|
|
|
- for (unsigned h = 0; h < newNode->height_; ++h)
|
|
|
|
|
|
|
+ root_ = head.GetChild(1);
|
|
|
|
|
+ if (root_)
|
|
|
{
|
|
{
|
|
|
- newNode->SetNext(h, fix[h]->GetNext(h));
|
|
|
|
|
- fix[h]->SetNext(h, newNode);
|
|
|
|
|
|
|
+ root_->isRed_ = false;
|
|
|
|
|
+ root_->parent_ = 0;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- ++size_;
|
|
|
|
|
- return newNode;
|
|
|
|
|
|
|
+ return removed;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- /// Allocate a node and its next pointers
|
|
|
|
|
- Node* AllocateNode(unsigned height, const T& key = T())
|
|
|
|
|
|
|
+ /// Erase the nodes recursively
|
|
|
|
|
+ void EraseNodes(Node* node)
|
|
|
{
|
|
{
|
|
|
- unsigned char* block = new unsigned char[sizeof(Node) + (height - 1) * sizeof(Node*)];
|
|
|
|
|
- Node* newNode = reinterpret_cast<Node*>(block);
|
|
|
|
|
-
|
|
|
|
|
- // Construct the pair with placement new and map the next pointers' address
|
|
|
|
|
- new(&newNode->pair_) KeyValue(key);
|
|
|
|
|
- newNode->height_ = height;
|
|
|
|
|
- if (height > 1)
|
|
|
|
|
- newNode->levels_ = reinterpret_cast<SkipListNodeBase**>(block + sizeof(Node));
|
|
|
|
|
- else
|
|
|
|
|
- newNode->levels_ = 0;
|
|
|
|
|
|
|
+ Node* left = node->GetChild(0);
|
|
|
|
|
+ Node* right = node->GetChild(1);
|
|
|
|
|
+ delete node;
|
|
|
|
|
+ --size_;
|
|
|
|
|
|
|
|
- return newNode;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /// Delete a node
|
|
|
|
|
- void DeleteNode(Node* node)
|
|
|
|
|
- {
|
|
|
|
|
- // Destruct the pair, then delete the memory block
|
|
|
|
|
- (&node->pair_)->~KeyValue();
|
|
|
|
|
- delete[] reinterpret_cast<unsigned char*>(node);
|
|
|
|
|
|
|
+ if (left)
|
|
|
|
|
+ EraseNodes(left);
|
|
|
|
|
+ if (right)
|
|
|
|
|
+ EraseNodes(right);
|
|
|
}
|
|
}
|
|
|
};
|
|
};
|