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*/