Open
Graph Drawing
Framework

 v.2012.05
 

Skiplist.h
Go to the documentation of this file.
00001 /*
00002  * $Revision: 2299 $
00003  * 
00004  * last checkin:
00005  *   $Author: gutwenger $ 
00006  *   $Date: 2012-05-07 15:57:08 +0200 (Mon, 07 May 2012) $ 
00007  ***************************************************************/
00008  
00043 #ifndef OGDF_SKIPLIST_H
00044 #define OGDF_SKIPLIST_H
00045 
00046 #include <ogdf/basic/basic.h>
00047 
00048 namespace ogdf {
00049 
00050 template<class X> class SkiplistIterator;
00051 
00053 
00061 template<class X> class Skiplist {
00062     friend class SkiplistIterator<X>;
00063     friend class Element;
00064     
00066     class Element {
00067         friend class Skiplist<X>;
00068         friend class SkiplistIterator<X>;
00069     
00070         X entry; // content
00071         Element** next; // successor elements
00072     
00073         // construction
00074         Element(const X &item, int height) :
00075                 entry(item) {
00076             next = (Element**)malloc(height*sizeof(Element*));
00077         }
00078         
00079         ~Element() {
00080             free(next);
00081         }
00082     
00083         OGDF_NEW_DELETE
00084     };
00085     
00086 public:
00087 
00089     Skiplist() : lSize(0) {
00090         srand(time(NULL));
00091         realheight = 5;
00092         height = 1;
00093         start = (Element**)malloc(realheight*sizeof(Element*));
00094         start[0] = NULL;
00095     }
00096     
00097     ~Skiplist() {
00098         clear();
00099         free(start);
00100     }
00101 
00103     bool isElement(X item) const {
00104         int h = height - 1;
00105         Element** cur = start; // wheeha!
00106         while(true) {   
00107             if( cur[h] && *(cur[h]->entry) < *item ) //nxt != NULL
00108                 cur = cur[h]->next;
00109             else if(--h < 0)
00110                 return cur[0] && *(cur[0]->entry) == *item;
00111         }
00112     }
00113     
00115     void add(X item) {
00116         lSize++;
00117         
00118         int nh = random_height();
00119         Element* n = OGDF_NEW Element(item, nh);
00120         if(nh > height)
00121             grow(nh);           
00122 
00123         int h = height - 1;
00124         Element** cur = start; // wheeha!
00125         while(true)  {  
00126             if( cur[h] && *(cur[h]->entry) < *item ) //nxt != NULL
00127                 cur = cur[h]->next;
00128             else {
00129                 if(h < nh) { // add only if new element is high enough
00130                     n->next[h] = cur[h];
00131                     cur[h] = n;
00132                 }
00133                 if(--h < 0)
00134                     return;
00135             }
00136         }
00137     }   
00138 
00140     int size() const { return lSize; }
00141     
00143     int empty() const { return (lSize==0); }
00144 
00146 
00150     void clear(bool killData = false) {
00151         Element* item = start[0];
00152         Element* old;
00153         while(item) {
00154             old = item;
00155             item = item->next[0];
00156             if(killData)
00157                 delete old->entry;
00158             delete old;
00159         }
00160         lSize = 0;
00161         height = 1;
00162         start[0] = 0;
00163     }
00164     
00166     const SkiplistIterator<X> begin() const { return start[0]; }
00167 
00168 private:
00169     int lSize;
00170     Element** start;
00171     int height;
00172     int realheight;
00173 
00174     int random_height() {
00175         int h = 1;
00176         while(rand() > RAND_MAX/2) h++;
00177         return h;
00178     }
00179     
00180     void grow(int newheight) {
00181         if(newheight > realheight) {
00182             realheight = newheight;
00183             start = (Element**)realloc(start, realheight*sizeof(Element*));
00184         }
00185         for(int i = newheight; i-->height;) {
00186             start[i] = NULL;
00187         }
00188         height = newheight;
00189     }
00190     
00191 };
00192 
00194 template<class X> class SkiplistIterator {
00195     friend class Skiplist<X>;
00196     
00197     const typename Skiplist<X>::Element *el;
00198     
00199     SkiplistIterator(const typename Skiplist<X>::Element *e) { el = e; }
00200     
00201 public:
00202 
00204     const X &operator*() const { return el->entry; }
00205     
00206     bool valid() const { return el; }
00207     
00209     SkiplistIterator<X> &operator++() {
00210         el = el->next[0];
00211         return *this;
00212     }
00214     SkiplistIterator<X> operator++(int) {
00215         SkiplistIterator<X> it = *this;
00216         el = el->next[0];
00217         return it;
00218     }   
00219 
00221     SkiplistIterator<X> &operator=(const SkiplistIterator<X> &it) {
00222         el = it.el;
00223         return *this;
00224     }
00225 };
00226 
00227 }
00228 
00229 #endif /*OGDF_SKIPLIST_H*/