Some C++ code for skip lists. For tutorial purposes. Not industrial strength. Thomas Anastasio 8 March 1999 template class SkipListNode { private: int _size; // number of levels in this node Array _forward; // forward pointers T datum; // datum stored at this node protected: inline void SetDatum(T & datum); inline void SetForward(int i, SkipListNode * f); inline void SetSize(int sz); public: SkipListNode(); SkipListNode(int size); SkipListNode(T & data, int size); SkipListNode(const SkipListNode &); ~SkipListNode(); inline T & GetDatum(); inline int GetSize(); inline SkipListNode * GetForward(int level); friend class SkipList; }; template class SkipList { private: int _high_node_size; // highest-level node now in this list int _max_node_size; // highest-level node allowed in this list double prob; // probability associated with this list SkipListNode * _head; // header node of this list protected: // Search for item in this skiplist, starting at startnode // startnode will usually be the header. If item is found, // return the node at which it is found with success equal true. // Otherwise, return the preceding node with success equal false. // Precondition: startnode is not NULL SkipListNode * Search(T & item, SkipListNode * startnode); // Accessor for _head inline SkipListNode * GetHeader(); // Finds the point at which item would be inserted using a node // of the given size. // Returns a "lookback" node that has each of its forward // pointers set to the closest node at that level. SkipListNode * FindInsertPoint(T & item, int nodesize) // insert item into this skiplist, using a node of the // specified size. Return true if successful bool Insert(T & item, int nodesize); public: SkipList(); // use max_node_size of 16, prob of 0.25 SkipList(int max_node_size, double probab); SkipList(const SkipList &); ~SkipList(); int GetHighNodeSize(); // size of node with most levels // insert item into this skiplist. Return true if insertion // succeeds, false otherwise. bool Insert(T & item); // Search for item in skiplist. If found, return the item with // success equal true. Otherwise, return a dummy item with // success equal false. T & Search(T & item, bool & success); // delete the first occurrence of the specified item bool Delete(T & item); }; template T & SkipList::Search(T & item, bool & success) { success = false; if (IsEmpty()) return item; // dummy value, not to be used SkipListNode * p = Search(T, GetHeader()); if (p->GetDatum() == item) success = true; return p->GetDatum(); } template SkipListNode * SkipList::Search(T & item, SkipListNode * p) { for (int i = p.GetSize() - 1; i >= 0; i--) { while (true) { if (p->GetForward(i) == NULL) break; // try next level T data = p->GetForward(i)->GetDatum(); if (data == item) // found it return p->GetForward(i); // not found yet if (item > data) p = p->GetForward(i); // skip ahead else break; // try next level } // while } // for return p; } template bool SkipList::Insert(T & item) { int nodesize = RandomNodeSize(GetMaxNodeSize()); return Insert(item, nodesize); } template bool SkipList::Insert(T & item, int nodesize) { SkipListNode * update = FindInsertPoint(item, nodesize); SkipListNode * newnode = new SkipListNode(item, nodesize); // newnode may have more levels than are currently in list // If so, adjust high_node_size of list. if (newsize > GetHighNodeSize()) SetHighNodeSize(newsize); for (int i = 0; i < newsize; i++) { SkipListNode * prev = update->GetForward(i); SkipListNode * next = prev->GetForward(i); newnode->SetForward(i, next); prev->SetForward(i, newnode); } IncrementListSize(); return true; } template bool SkipList::Delete(T & item) { if (IsEmpty()) // no deletion from empty list return false; SkipListNode * update = FindInsertPoint(item,GetHighNodeSize()); for (int i = 0; i < GetHighNodeSize(); i++) { SkipListNode * prev = update->GetForward(i); SkipListNode * next = prev->GetForward(i); if (next->GetDatum() != item) // at level above target break; // node's level // unlink the target node next = next->GetForward(i); prev->SetForward(i, next); } DecrementListSize(); return true; } template SkipListNode * SkipList::FindInsertPoint(T & item, int nodesize) { SkipListNode * p = GetHeader(); SkipListNode * lookback = new SkipListNode(nodesize); int i; for (i = 0; i < nodesize; i++) lookback->SetForward(i, p); // all pointers to header for (i = nodesize - 1; i >= 0; i--) { while (true) { if (p->GetForward(i) == NULL) break; T data = p->GetForward(i)->GetDatum(); if (data < item) p = p->GetForward(); else break; } // while lookback->SetForward(i, p); } return lookback; }