Răsfoiți Sursa

Tidied up Map & Set code and added bidirectional iteration.

Lasse Öörni 14 ani în urmă
părinte
comite
b447f1d030
3 a modificat fișierele cu 316 adăugiri și 173 ștergeri
  1. 76 0
      Engine/Core/Iterator.h
  2. 123 91
      Engine/Core/Map.h
  3. 117 82
      Engine/Core/Set.h

+ 76 - 0
Engine/Core/Iterator.h

@@ -102,3 +102,79 @@ private:
     /// Pointer
     /// Pointer
     const T* ptr_;
     const T* ptr_;
 };
 };
+
+/// List node base
+struct ListNodeBase
+{
+    ListNodeBase() :
+        prev_(0),
+        next_(0)
+    {
+    }
+    
+    /// Previous node
+    ListNodeBase* prev_;
+    /// Next node
+    ListNodeBase* next_;
+};
+
+/// Skip list node base
+struct SkipListNodeBase : public ListNodeBase
+{
+    /// Node height
+    unsigned height_;
+    /// Skip list pointers for heights > 1
+    SkipListNodeBase** levels_;
+    
+    /// Return next node on a specific height
+    SkipListNodeBase* GetNext(unsigned height) const
+    {
+        if (!height)
+            return static_cast<SkipListNodeBase*>(next_);
+        else
+            return levels_[height - 1];
+    }
+    
+    /// Return previous node
+    SkipListNodeBase* GetPrev() const { return static_cast<SkipListNodeBase*>(prev_); }
+    
+    // Set next node on a specific height
+    void SetNext(unsigned height, SkipListNodeBase* node)
+    {
+        if (!height)
+            next_ = node;
+        else
+            levels_[height - 1] = node;
+    }
+    
+    /// Set previous node
+    void SetPrev(SkipListNodeBase* node) { prev_ = node; }
+};
+
+/// List iterator base class
+class ListIteratorBase
+{
+public:
+    /// Test for equality with another iterator
+    bool operator == (const ListIteratorBase& rhs) const { return ptr_ == rhs.ptr_; }
+    /// Test for inequality with another iterator
+    bool operator != (const ListIteratorBase& rhs) const { return ptr_ != rhs.ptr_; }
+    
+    /// Go to the next node
+    void operator ++ ()
+    {
+        if (ptr_->next_)
+            ptr_ = ptr_->next_;
+    }
+    
+    /// Go to the previous node
+    void operator -- ()
+    {
+        if (ptr_->prev_)
+            ptr_ = ptr_->prev_;
+    }
+    
+protected:
+    /// Node pointer
+    ListNodeBase* ptr_;
+};

+ 123 - 91
Engine/Core/Map.h

@@ -61,18 +61,26 @@ public:
     };
     };
     
     
     /// Map node
     /// Map node
-    struct Node
+    struct Node : public SkipListNodeBase
     {
     {
         /// Key-value pair
         /// Key-value pair
         KeyValue pair_;
         KeyValue pair_;
-        /// Node height
-        unsigned height_;
-        /// Skip list pointers
-        Node** next_;
+        
+        /// Return next node on a specific height
+        Node* GetNext(unsigned height) const
+        {
+            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_); }
     };
     };
     
     
     /// Map node iterator
     /// Map node iterator
-    class Iterator
+    class Iterator : public ListIteratorBase
     {
     {
     public:
     public:
         explicit Iterator(Node* ptr) :
         explicit Iterator(Node* ptr) :
@@ -81,30 +89,13 @@ public:
         }
         }
         
         
         /// Point to the pair
         /// Point to the pair
-        KeyValue* operator -> () const { return &ptr_->pair_; }
+        T* operator -> () const { return &(static_cast<Node*>(ptr_))->pair_; }
         /// Dereference the pair
         /// Dereference the pair
-        KeyValue& operator * () const { return ptr_->pair_; }
-        /// Test for equality with another iterator
-        bool operator == (const Iterator& rhs) const { return ptr_ == rhs.ptr_; }
-        /// Test for inequality with another iterator
-        bool operator != (const Iterator& rhs) const { return ptr_ != rhs.ptr_; }
-        /// Return whether non-null
-        operator bool () const { return ptr_ != 0; }
-        
-        /// Go to the next node, or to null if at the end
-        void operator ++ ()
-        {
-            if (ptr_)
-                ptr_ = ptr_->next_[0];
-        }
-        
-    private:
-        /// Node pointer
-        Node* ptr_;
+        T& operator * () const { return (static_cast<Node*>(ptr_))->pair_; }
     };
     };
     
     
     /// Map node const iterator
     /// Map node const iterator
-    class ConstIterator
+    class ConstIterator : public ListIteratorBase
     {
     {
     public:
     public:
         explicit ConstIterator(Node* ptr) :
         explicit ConstIterator(Node* ptr) :
@@ -113,26 +104,9 @@ public:
         }
         }
         
         
         /// Point to the pair
         /// Point to the pair
-        const KeyValue* operator -> () const { return &ptr_->pair_; }
+        const T* operator -> () const { return &(static_cast<Node*>(ptr_))->pair_; }
         /// Dereference the pair
         /// Dereference the pair
-        const KeyValue& operator * () const { return ptr_->pair_; }
-        /// Test for equality with another iterator
-        bool operator == (const ConstIterator& rhs) const { return ptr_ == rhs.ptr_; }
-        /// Test for inequality with another iterator
-        bool operator != (const ConstIterator& rhs) const { return ptr_ != rhs.ptr_; }
-        /// Return whether non-null
-        operator bool () const { return ptr_ != 0; }
-        
-        /// Go to the next node, or to null if at the end
-        void operator ++ ()
-        {
-            if (ptr_)
-                ptr_ = ptr_->next_[0];
-        }
-        
-    private:
-        /// Node pointer
-        Node* ptr_;
+        const T& operator * () const { return (static_cast<Node*>(ptr_))->pair_; }
     };
     };
     
     
     /// Construct empty
     /// Construct empty
@@ -142,10 +116,14 @@ public:
         size_(0),
         size_(0),
         bitsLeft_(0)
         bitsLeft_(0)
     {
     {
-        // Allocate the head node and zero the next pointers
+        // Allocate the head and tail nodes and zero the next pointers
         head_ = AllocateNode(maxHeight_, T());
         head_ = AllocateNode(maxHeight_, T());
+        tail_ = AllocateNode(maxHeight_, T());
         for (unsigned i = 0; i < maxHeight_; ++i)
         for (unsigned i = 0; i < maxHeight_; ++i)
-            head_->next_[i] = 0;
+        {
+            head_->SetNext(i, tail_);
+            tail_->SetNext(i, 0);
+        }
         
         
         // Allocate the fixup pointers
         // Allocate the fixup pointers
         fix_ = new Node*[maxHeight_];
         fix_ = new Node*[maxHeight_];
@@ -158,14 +136,19 @@ public:
         size_(0),
         size_(0),
         bitsLeft_(0)
         bitsLeft_(0)
     {
     {
-        // Allocate the head node and zero the next pointers
-        head_ = AllocateNode(maxHeight_);
+        // Allocate the head and tail nodes and zero the next pointers
+        head_ = AllocateNode(maxHeight_, T());
+        tail_ = AllocateNode(maxHeight_, T());
         for (unsigned i = 0; i < maxHeight_; ++i)
         for (unsigned i = 0; i < maxHeight_; ++i)
-            head_->next_[i] = 0;
-        
+        {
+            head_->SetNext(i, tail_);
+            tail_->SetNext(i, 0);
+        }
+
         // Allocate the fixup pointers
         // Allocate the fixup pointers
         fix_ = new Node*[maxHeight_];
         fix_ = new Node*[maxHeight_];
         
         
+        // Then assign the another map
         *this = map;
         *this = map;
     }
     }
     
     
@@ -174,6 +157,7 @@ public:
     {
     {
         Clear();
         Clear();
         DeleteNode(head_);
         DeleteNode(head_);
+        DeleteNode(tail_);
         delete[] fix_;
         delete[] fix_;
     }
     }
     
     
@@ -273,10 +257,13 @@ public:
     void Insert(const Iterator& start, const Iterator& end)
     void Insert(const Iterator& start, const Iterator& end)
     {
     {
         Iterator it = start;
         Iterator it = start;
-        while ((it) && (it != end))
+        while (it != end)
         {
         {
-            Insert(*it);
-            ++it;
+            Iterator current = it++;
+            Insert(*current);
+            // Break if the iterator got stuck
+            if (it == current)
+                break;
         }
         }
     }
     }
     
     
@@ -287,28 +274,42 @@ public:
         
         
         for (unsigned j = height_ - 1; j < MAX_HEIGHT; --j)
         for (unsigned j = height_ - 1; j < MAX_HEIGHT; --j)
         {
         {
-            while ((i->next_[j]) && (key > i->next_[j]->pair_.first_))
-                i = i->next_[j];
+            for (;;)
+            {
+                Node* next = i->GetNext(j);
+                if ((next) && (next != tail_) && (key > next->pair_.first_))
+                    i = next;
+                else
+                    break;
+            }
             fix_[j] = i;
             fix_[j] = i;
         }
         }
         
         
         // Check if key does not exist
         // Check if key does not exist
-        if ((!i->next_[0]) && (i->next_[0]->pair_.first_ != key))
+        Node* toRemove = i->GetNext(0);
+        if ((!toRemove) || (toRemove == tail_) || (toRemove->pair_.first_ != key))
             return false;
             return false;
         
         
-        Node* toRemove = fix_[0]->next_[0];
+        // 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)
         for (unsigned j = 0; j < height_; ++j)
         {
         {
-            if (fix_[j]->next_[j])
-                fix_[j]->next_[j] = fix_[j]->next_[j]->next_[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)
         while (height_ > 0)
         {
         {
-            if (head_->next_[height_ - 1])
+            if (head_->GetNext(height_ - 1))
                 break;
                 break;
-            head_->next_[--height_] = 0;
+            head_->SetNext(--height_, 0);
         }
         }
         
         
         DeleteNode(toRemove);
         DeleteNode(toRemove);
@@ -332,9 +333,12 @@ public:
     Iterator Erase(const Iterator& start, const Iterator& end)
     Iterator Erase(const Iterator& start, const Iterator& end)
     {
     {
         Iterator it = start;
         Iterator it = start;
-        while ((it) && (it != end))
+        while (it != end)
         {
         {
             Iterator current = it++;
             Iterator current = it++;
+            // Break if the iterator got stuck
+            if (it == current)
+                break;
             Erase(current->first_);
             Erase(current->first_);
         }
         }
         
         
@@ -344,16 +348,20 @@ public:
     /// Clear the map
     /// Clear the map
     void Clear()
     void Clear()
     {
     {
-        // Let the head node remain, but clear its next pointers
-        Node* node = head_->next_[0];
-        for (unsigned i = 0; i < height_; ++i)
-            head_->next_[i] = 0;
+        // Let the head and tails node remain, but reset the next pointers
+        Node* node = head_->GetNext(0);
+        for (unsigned i = 0; i < maxHeight_; ++i)
+        {
+            head_->SetNext(i, tail_);
+            tail_->SetNext(i, 0);
+            tail_->SetPrev(0);
+        }
         
         
-        // Then remove all the nodes
-        while (node)
+        // Then remove all the key nodes
+        while (node != tail_)
         {
         {
             Node* current = node;
             Node* current = node;
-            node = node->next_[0];
+            node = node->GetNext(0);
             DeleteNode(current);
             DeleteNode(current);
         }
         }
         
         
@@ -367,12 +375,12 @@ public:
     ConstIterator Find(const T& key) const { return ConstIterator(FindNode(key)); }
     ConstIterator Find(const T& key) const { return ConstIterator(FindNode(key)); }
     /// Return iterator to the first actual node
     /// Return iterator to the first actual node
     Iterator Begin() { return Iterator(head_->next_[0]); }
     Iterator Begin() { return Iterator(head_->next_[0]); }
-    /// Return iterator to the end (null iterator)
-    Iterator End() { return Iterator(0); }
-    /// Return const iterator to the first actual node
+    /// Return iterator to the first actual node
     ConstIterator Begin() const { return ConstIterator(head_->next_[0]); }
     ConstIterator Begin() const { return ConstIterator(head_->next_[0]); }
-    /// Return const iterator to the end (null iterator)
-    ConstIterator End() const { return ConstIterator(0); }
+    /// Return iterator to the end
+    Iterator End() { return Iterator(tail_); }
+    /// Return iterator to the end
+    ConstIterator End() const { return ConstIterator(tail_); }
     /// Return whether contains a key
     /// Return whether contains a key
     bool Contains(const T& key) const { return FindNode(key) != 0; }
     bool Contains(const T& key) const { return FindNode(key) != 0; }
     /// Return number of keys
     /// Return number of keys
@@ -391,12 +399,19 @@ private:
         Node* i = head_;
         Node* i = head_;
         for (unsigned j = height_ - 1; j < MAX_HEIGHT; --j)
         for (unsigned j = height_ - 1; j < MAX_HEIGHT; --j)
         {
         {
-            while ((i->next_[j]) && (key > i->next_[j]->pair_.first_))
-                i = i->next_[j];
+            for (;;)
+            {
+                Node* next = i->GetNext(j);
+                if ((next) && (next != tail_) && (key > next->pair_.first_)) 
+                    i = next;
+                else
+                    break;
+            }
         }
         }
         
         
-        if ((i->next_[0]) && (i->next_[0]->pair_.first_ == key))
-            return i->next_[0];
+        Node* next = i->GetNext(0);
+        if ((next) && (next != tail_) && (next->pair_.first_ == key))
+            return next;
         else
         else
             return 0;
             return 0;
     }
     }
@@ -408,32 +423,44 @@ private:
         
         
         for (unsigned j = height_ - 1; j < MAX_HEIGHT; --j)
         for (unsigned j = height_ - 1; j < MAX_HEIGHT; --j)
         {
         {
-            while ((i->next_[j]) && (pair.first_ > i->next_[j]->pair_.first_))
-                i = i->next_[j];
+            for (;;)
+            {
+                Node* next = i->GetNext(j);
+                if ((next) && (next != tail_) && (pair.first_ > next->pair_.first_))
+                    i = next;
+                else
+                    break;
+            }
             fix_[j] = i;
             fix_[j] = i;
         }
         }
         
         
-        // Check if key already exists, in that case modify just the value
-        if ((i->next_[0]) && (i->next_[0]->pair_.first_ == pair.first_))
+        // 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_))
         {
         {
-            Node* existing = i->next_[0];
-            existing->pair_.second_ = pair.second_;
-            return existing;
+            next->pair_.second_ = pair.second_;
+            return next;
         }
         }
         
         
-        // Create new node, assign height and pair
+        // Create new node, assign height and key
         if (!height)
         if (!height)
             height = GetHeight();
             height = GetHeight();
         Node* newNode = AllocateNode(height, pair.first_);
         Node* newNode = AllocateNode(height, pair.first_);
         newNode->pair_.second_ = pair.second_;
         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_)
         while (newNode->height_ > height_)
             fix_[height_++] = head_;
             fix_[height_++] = head_;
         
         
         for (unsigned h = 0; h < newNode->height_; ++h)
         for (unsigned h = 0; h < newNode->height_; ++h)
         {
         {
-            newNode->next_[h] = fix_[h]->next_[h];
-            fix_[h]->next_[h] = newNode;
+            newNode->SetNext(h, fix_[h]->GetNext(h));
+            fix_[h]->SetNext(h, newNode);
         }
         }
         
         
         ++size_;
         ++size_;
@@ -469,13 +496,16 @@ private:
     /// Allocate a node and its next pointers
     /// Allocate a node and its next pointers
     Node* AllocateNode(unsigned height, const T& key)
     Node* AllocateNode(unsigned height, const T& key)
     {
     {
-        unsigned char* block = new unsigned char[sizeof(Node) + height * sizeof(Node*)];
+        unsigned char* block = new unsigned char[sizeof(Node) + (height - 1) * sizeof(Node*)];
         Node* newNode = reinterpret_cast<Node*>(block);
         Node* newNode = reinterpret_cast<Node*>(block);
         
         
         // Construct the pair with placement new and map the next pointers' address
         // Construct the pair with placement new and map the next pointers' address
         new(&newNode->pair_) KeyValue(key);
         new(&newNode->pair_) KeyValue(key);
         newNode->height_ = height;
         newNode->height_ = height;
-        newNode->next_ = reinterpret_cast<Node**>(block + sizeof(Node));
+        if (height > 1)
+            newNode->levels_ = reinterpret_cast<SkipListNodeBase**>(block + sizeof(Node));
+        else
+            newNode->levels_ = 0;
         
         
         return newNode;
         return newNode;
     }
     }
@@ -490,6 +520,8 @@ private:
     
     
     /// Head node pointer
     /// Head node pointer
     Node* head_;
     Node* head_;
+    /// Tail node pointer
+    Node* tail_;
     /// Fixup pointers for insert & erase
     /// Fixup pointers for insert & erase
     Node** fix_;
     Node** fix_;
     /// Maximum height
     /// Maximum height

+ 117 - 82
Engine/Core/Set.h

@@ -23,6 +23,8 @@
 
 
 #pragma once
 #pragma once
 
 
+#include "Iterator.h"
+
 #include <cstdlib>
 #include <cstdlib>
 #include <new>
 #include <new>
 
 
@@ -33,18 +35,26 @@ template <class T> class Set
 {
 {
 public:
 public:
     /// Set node
     /// Set node
-    struct Node
+    struct Node : public SkipListNodeBase
     {
     {
         /// Key
         /// Key
         T key_;
         T key_;
-        /// Node height
-        unsigned height_;
-        /// Skip list pointers
-        Node** next_;
+        
+        /// Return next node on a specific height
+        Node* GetNext(unsigned height) const
+        {
+            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_); }
     };
     };
     
     
     /// Set node iterator
     /// Set node iterator
-    class Iterator
+    class Iterator : public ListIteratorBase
     {
     {
     public:
     public:
         explicit Iterator(Node* ptr) :
         explicit Iterator(Node* ptr) :
@@ -53,30 +63,13 @@ public:
         }
         }
         
         
         /// Point to the key
         /// Point to the key
-        const T* operator -> () const { return &ptr_->key_; }
+        const T* operator -> () const { return &(static_cast<Node*>(ptr_))->key_; }
         /// Dereference the key
         /// Dereference the key
-        const T& operator * () const { return ptr_->key_; }
-        /// Test for equality with another iterator
-        bool operator == (const Iterator& rhs) const { return ptr_ == rhs.ptr_; }
-        /// Test for inequality with another iterator
-        bool operator != (const Iterator& rhs) const { return ptr_ != rhs.ptr_; }
-        /// Return whether non-null
-        operator bool () const { return ptr_ != 0; }
-        
-        /// Go to the next node, or to null if at the end
-        void operator ++ ()
-        {
-            if (ptr_)
-                ptr_ = ptr_->next_[0];
-        }
-        
-    private:
-        /// Node pointer
-        Node* ptr_;
+        const T& operator * () const { return (static_cast<Node*>(ptr_))->key_; }
     };
     };
     
     
     /// Set node const iterator
     /// Set node const iterator
-    class ConstIterator
+    class ConstIterator : public ListIteratorBase
     {
     {
     public:
     public:
         explicit ConstIterator(Node* ptr) :
         explicit ConstIterator(Node* ptr) :
@@ -85,28 +78,11 @@ public:
         }
         }
         
         
         /// Point to the key
         /// Point to the key
-        const T* operator -> () const { return &ptr_->key_; }
+        const T* operator -> () const { return &(static_cast<Node*>(ptr_))->key_; }
         /// Dereference the key
         /// Dereference the key
-        const T& operator * () const { return ptr_->key_; }
-        /// Test for equality with anoter iterator
-        bool operator == (const ConstIterator& rhs) const { return ptr_ == rhs.ptr_; }
-        /// Test for inequality with another iterator
-        bool operator != (const ConstIterator& rhs) const { return ptr_ != rhs.ptr_; }
-        /// Return whether non-null
-        operator bool () const { return ptr_ != 0; }
-        
-        /// Go to the next node, or to null if at the end
-        void operator ++ ()
-        {
-            if (ptr_)
-                ptr_ = ptr_->next_[0];
-        }
-        
-    private:
-        /// Node pointer
-        Node* ptr_;
+        const T& operator * () const { return (static_cast<Node*>(ptr_))->key_; }
     };
     };
-    
+
     /// Construct empty
     /// Construct empty
     Set(unsigned maxHeight = MAX_HEIGHT) :
     Set(unsigned maxHeight = MAX_HEIGHT) :
         maxHeight_(maxHeight < MAX_HEIGHT ? maxHeight : MAX_HEIGHT),
         maxHeight_(maxHeight < MAX_HEIGHT ? maxHeight : MAX_HEIGHT),
@@ -114,10 +90,14 @@ public:
         size_(0),
         size_(0),
         bitsLeft_(0)
         bitsLeft_(0)
     {
     {
-        // Allocate the head node and zero the next pointers
+        // Allocate the head and tail nodes and zero the next pointers
         head_ = AllocateNode(maxHeight_);
         head_ = AllocateNode(maxHeight_);
+        tail_ = AllocateNode(maxHeight_);
         for (unsigned i = 0; i < maxHeight_; ++i)
         for (unsigned i = 0; i < maxHeight_; ++i)
-            head_->next_[i] = 0;
+        {
+            head_->SetNext(i, tail_);
+            tail_->SetNext(i, 0);
+        }
         
         
         // Allocate the fixup pointers
         // Allocate the fixup pointers
         fix_ = new Node*[maxHeight_];
         fix_ = new Node*[maxHeight_];
@@ -130,14 +110,19 @@ public:
         size_(0),
         size_(0),
         bitsLeft_(0)
         bitsLeft_(0)
     {
     {
-        // Allocate the head node and zero the next pointers
+        // Allocate the head and tail nodes and zero the next pointers
         head_ = AllocateNode(maxHeight_);
         head_ = AllocateNode(maxHeight_);
+        tail_ = AllocateNode(maxHeight_);
         for (unsigned i = 0; i < maxHeight_; ++i)
         for (unsigned i = 0; i < maxHeight_; ++i)
-            head_->next_[i] = 0;
+        {
+            head_->SetNext(i, tail_);
+            tail_->SetNext(i, 0);
+        }
         
         
         // Allocate the fixup pointers
         // Allocate the fixup pointers
         fix_ = new Node*[maxHeight_];
         fix_ = new Node*[maxHeight_];
         
         
+        // Then assign the another set
         *this = set;
         *this = set;
     }
     }
     
     
@@ -146,6 +131,7 @@ public:
     {
     {
         Clear();
         Clear();
         DeleteNode(head_);
         DeleteNode(head_);
+        DeleteNode(tail_);
         delete[] fix_;
         delete[] fix_;
     }
     }
     
     
@@ -227,8 +213,11 @@ public:
         Iterator it = start;
         Iterator it = start;
         while ((it) && (it != end))
         while ((it) && (it != end))
         {
         {
-            Insert(*it);
-            ++it;
+            Iterator current = it++;
+            Insert(*current);
+            // Break if the iterator got stuck
+            if (it == current)
+                break;
         }
         }
     }
     }
     
     
@@ -239,28 +228,42 @@ public:
         
         
         for (unsigned j = height_ - 1; j < MAX_HEIGHT; --j)
         for (unsigned j = height_ - 1; j < MAX_HEIGHT; --j)
         {
         {
-            while ((i->next_[j]) && (key > i->next_[j]->key_))
-                i = i->next_[j];
+            for (;;)
+            {
+                Node* next = i->GetNext(j);
+                if ((next) && (next != tail_) && (key > next->key_))
+                    i = next;
+                else
+                    break;
+            }
             fix_[j] = i;
             fix_[j] = i;
         }
         }
         
         
         // Check if key does not exist
         // Check if key does not exist
-        if ((!i->next_[0]) && (i->next_[0]->key_ != key))
+        Node* toRemove = i->GetNext(0);
+        if ((!toRemove) || (toRemove == tail_) || (toRemove->key_ != key))
             return false;
             return false;
         
         
-        Node* toRemove = fix_[0]->next_[0];
+        // 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)
         for (unsigned j = 0; j < height_; ++j)
         {
         {
-            if (fix_[j]->next_[j])
-                fix_[j]->next_[j] = fix_[j]->next_[j]->next_[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)
         while (height_ > 0)
         {
         {
-            if (head_->next_[height_ - 1])
+            if (head_->GetNext(height_ - 1))
                 break;
                 break;
-            head_->next_[--height_] = 0;
+            head_->SetNext(--height_, 0);
         }
         }
         
         
         DeleteNode(toRemove);
         DeleteNode(toRemove);
@@ -284,9 +287,12 @@ public:
     Iterator Erase(const Iterator& start, const Iterator& end)
     Iterator Erase(const Iterator& start, const Iterator& end)
     {
     {
         Iterator it = start;
         Iterator it = start;
-        while ((it) && (it != end))
+        while (it != end)
         {
         {
             Iterator current = it++;
             Iterator current = it++;
+            // Break if the iterator got stuck
+            if (it == current)
+                break;
             Erase(*current);
             Erase(*current);
         }
         }
         
         
@@ -296,16 +302,20 @@ public:
     /// Clear the set
     /// Clear the set
     void Clear()
     void Clear()
     {
     {
-        // Let the head node remain, but clear its next pointers
-        Node* node = head_->next_[0];
-        for (unsigned i = 0; i < height_; ++i)
-            head_->next_[i] = 0;
+        // Let the head and tails node remain, but reset the next pointers
+        Node* node = head_->GetNext(0);
+        for (unsigned i = 0; i < maxHeight_; ++i)
+        {
+            head_->SetNext(i, tail_);
+            tail_->SetNext(i, 0);
+            tail_->SetPrev(0);
+        }
         
         
         // Then remove all the key nodes
         // Then remove all the key nodes
-        while (node)
+        while (node != tail_)
         {
         {
             Node* current = node;
             Node* current = node;
-            node = node->next_[0];
+            node = node->GetNext(0);
             DeleteNode(current);
             DeleteNode(current);
         }
         }
         
         
@@ -321,10 +331,10 @@ public:
     Iterator Begin() { return Iterator(head_->next_[0]); }
     Iterator Begin() { return Iterator(head_->next_[0]); }
     /// Return iterator to the first actual node
     /// Return iterator to the first actual node
     ConstIterator Begin() const { return ConstIterator(head_->next_[0]); }
     ConstIterator Begin() const { return ConstIterator(head_->next_[0]); }
-    /// Return iterator to the end (null iterator)
-    Iterator End() { return Iterator(0); }
-    /// Return iterator to the end (null iterator)
-    ConstIterator End() const { return ConstIterator(0); }
+    /// Return iterator to the end
+    Iterator End() { return Iterator(tail_); }
+    /// Return iterator to the end
+    ConstIterator End() const { return ConstIterator(tail_); }
     /// Return whether contains a key
     /// Return whether contains a key
     bool Contains(const T& key) const { return FindNode(key) != 0; }
     bool Contains(const T& key) const { return FindNode(key) != 0; }
     /// Return number of keys
     /// Return number of keys
@@ -343,12 +353,19 @@ private:
         Node* i = head_;
         Node* i = head_;
         for (unsigned j = height_ - 1; j < MAX_HEIGHT; --j)
         for (unsigned j = height_ - 1; j < MAX_HEIGHT; --j)
         {
         {
-            while ((i->next_[j]) && (key > i->next_[j]->key_))
-                i = i->next_[j];
+            for (;;)
+            {
+                Node* next = i->GetNext(j);
+                if ((next) && (next != tail_) && (key > next->key_)) 
+                    i = next;
+                else
+                    break;
+            }
         }
         }
         
         
-        if ((i->next_[0]) && (i->next_[0]->key_ == key))
-            return i->next_[0];
+        Node* next = i->GetNext(0);
+        if ((next) && (next != tail_) && (next->key_ == key))
+            return next;
         else
         else
             return 0;
             return 0;
     }
     }
@@ -360,13 +377,20 @@ private:
         
         
         for (unsigned j = height_ - 1; j < MAX_HEIGHT; --j)
         for (unsigned j = height_ - 1; j < MAX_HEIGHT; --j)
         {
         {
-            while ((i->next_[j]) && (key > i->next_[j]->key_))
-                i = i->next_[j];
+            for (;;)
+            {
+                Node* next = i->GetNext(j);
+                if ((next) && (next != tail_) && (key > next->key_))
+                    i = next;
+                else
+                    break;
+            }
             fix_[j] = i;
             fix_[j] = i;
         }
         }
         
         
         // Check if key already exists
         // Check if key already exists
-        if ((i->next_[0]) && (i->next_[0]->key_ == key))
+        Node* next = i->GetNext(0);
+        if ((next) && (next != tail_) && (next->key_ == key))
             return false;
             return false;
         
         
         // Create new node, assign height and key
         // Create new node, assign height and key
@@ -375,13 +399,19 @@ private:
         Node* newNode = AllocateNode(height);
         Node* newNode = AllocateNode(height);
         newNode->key_ = key;
         newNode->key_ = key;
         
         
+        // 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_)
         while (newNode->height_ > height_)
             fix_[height_++] = head_;
             fix_[height_++] = head_;
         
         
         for (unsigned h = 0; h < newNode->height_; ++h)
         for (unsigned h = 0; h < newNode->height_; ++h)
         {
         {
-            newNode->next_[h] = fix_[h]->next_[h];
-            fix_[h]->next_[h] = newNode;
+            newNode->SetNext(h, fix_[h]->GetNext(h));
+            fix_[h]->SetNext(h, newNode);
         }
         }
         
         
         ++size_;
         ++size_;
@@ -417,13 +447,16 @@ private:
     /// Allocate a node and its next pointers
     /// Allocate a node and its next pointers
     Node* AllocateNode(unsigned height)
     Node* AllocateNode(unsigned height)
     {
     {
-        unsigned char* block = new unsigned char[sizeof(Node) + height * sizeof(Node*)];
+        unsigned char* block = new unsigned char[sizeof(Node) + (height - 1) * sizeof(Node*)];
         Node* newNode = reinterpret_cast<Node*>(block);
         Node* newNode = reinterpret_cast<Node*>(block);
         
         
         // Construct the key with placement new and set the next pointers' address
         // Construct the key with placement new and set the next pointers' address
         new(&newNode->key_) T();
         new(&newNode->key_) T();
         newNode->height_ = height;
         newNode->height_ = height;
-        newNode->next_ = reinterpret_cast<Node**>(block + sizeof(Node));
+        if (height > 1)
+            newNode->levels_ = reinterpret_cast<SkipListNodeBase**>(block + sizeof(Node));
+        else
+            newNode->levels_ = 0;
         
         
         return newNode;
         return newNode;
     }
     }
@@ -438,6 +471,8 @@ private:
     
     
     /// Head node pointer
     /// Head node pointer
     Node* head_;
     Node* head_;
+    /// Tail node pointer
+    Node* tail_;
     /// Fixup pointers for insert & erase
     /// Fixup pointers for insert & erase
     Node** fix_;
     Node** fix_;
     /// Maximum height
     /// Maximum height