00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 extern "C"
00015 {
00016 #include <stdio.h>
00017 #include <stdlib.h>
00018 #include <assert.h>
00019
00020 #include "skiplist.h"
00021 }
00022
00023 #ifdef USE_DMALLOC
00024 # include <dmalloc.h>
00025 #endif
00026
00027 #ifndef MIN
00028 #define MIN(a,b) ((a<b)?(a):(b))
00029 #endif
00030
00031 static int get_b_rand(void) {
00032 static int ph=32;
00033 static unsigned long randseq;
00034 if(ph > 31) {
00035 ph=0;
00036 randseq = lrand48();
00037 }
00038 ph++;
00039 return ((randseq & (1 << (ph-1))) >> (ph-1));
00040 }
00041
00042 void skiplisti_init(Skiplist *sl) {
00043 sl->compare = (SkiplistComparator)NULL;
00044 sl->comparek = (SkiplistComparator)NULL;
00045 sl->height=0;
00046 sl->preheight=0;
00047 sl->size=0;
00048 sl->top = NULL;
00049 sl->bottom = NULL;
00050 sl->index = NULL;
00051 }
00052
00053 static int indexing_comp(void *a, void *b) {
00054 assert(a);
00055 assert(b);
00056 return (void *)(((Skiplist *)a)->compare)>(void *)(((Skiplist *)b)->compare);
00057 }
00058 static int indexing_compk(void *a, void *b) {
00059 assert(b);
00060 return a>(void *)(((Skiplist *)b)->compare);
00061 }
00062
00063 void skiplist_init(Skiplist *sl) {
00064 skiplisti_init(sl);
00065 sl->index = (Skiplist *)malloc(sizeof(Skiplist));
00066 skiplisti_init(sl->index);
00067 skiplist_set_compare(sl->index, indexing_comp, indexing_compk);
00068 }
00069
00070 void skiplist_set_compare(Skiplist *sl,
00071 SkiplistComparator comp,
00072 SkiplistComparator compk) {
00073 if(sl->compare && sl->comparek) {
00074 skiplist_add_index(sl, comp, compk);
00075 } else {
00076 sl->compare = comp;
00077 sl->comparek = compk;
00078 }
00079 }
00080
00081 void skiplist_add_index(Skiplist *sl,
00082 SkiplistComparator comp,
00083 SkiplistComparator compk) {
00084 struct skiplistnode *m;
00085 Skiplist *ni;
00086 int icount=0;
00087 #ifdef SLDEBUG
00088 fprintf(stderr, "Adding index to %p\n", sl);
00089 #endif
00090 skiplist_find(sl->index, (void *)comp, &m);
00091 if(m) return;
00092 ni = (Skiplist *)malloc(sizeof(Skiplist));
00093 skiplisti_init(ni);
00094 skiplist_set_compare(ni, comp, compk);
00095
00096 m = skiplist_insert(sl->index, ni);
00097 while(m->prev) m=m->prev, icount++;
00098 for(m=skiplist_getlist(sl); m; skiplist_next(sl, &m)) {
00099 int j=icount-1;
00100 struct skiplistnode *nsln;
00101 nsln = skiplist_insert(ni, m->data);
00102
00103 while(j>0) m=m->nextindex, j--;
00104
00105 nsln->nextindex = m->nextindex;
00106 if(m->nextindex) m->nextindex->previndex = nsln;
00107 nsln->previndex = m;
00108 m->nextindex = nsln;
00109 }
00110 }
00111
00112 struct skiplistnode *skiplist_getlist(Skiplist *sl) {
00113 if(!sl->bottom) return NULL;
00114 return sl->bottom->next;
00115 }
00116
00117 void *skiplist_find(Skiplist *sl,
00118 void *data,
00119 struct skiplistnode **iter) {
00120 void *ret;
00121 struct skiplistnode *aiter;
00122 if(!sl->compare) return 0;
00123 if(iter)
00124 ret = skiplist_find_compare(sl, data, iter, sl->compare);
00125 else
00126 ret = skiplist_find_compare(sl, data, &aiter, sl->compare);
00127 return ret;
00128 }
00129 void *skiplist_find_compare(Skiplist *sli,
00130 void *data,
00131 struct skiplistnode **iter,
00132 SkiplistComparator comp) {
00133 struct skiplistnode *m = NULL;
00134 Skiplist *sl;
00135 if(comp==sli->compare || !sli->index) {
00136 sl = sli;
00137 } else {
00138 skiplist_find(sli->index, (void *)comp, &m);
00139 assert(m);
00140 sl= (Skiplist *) m->data;
00141 }
00142 skiplisti_find_compare(sl, data, iter, sl->comparek);
00143 return (*iter)?((*iter)->data):(*iter);
00144 }
00145 int skiplisti_find_compare(Skiplist *sl,
00146 void *data,
00147 struct skiplistnode **ret,
00148 SkiplistComparator comp) {
00149 struct skiplistnode *m = NULL;
00150 int count=0;
00151 m = sl->top;
00152 while(m) {
00153 int compared;
00154 if(m->next) compared=comp(data, m->next->data);
00155 if(compared == 0) {
00156 #ifdef SL_DEBUG
00157 printf("Looking -- found in %d steps\n", count);
00158 #endif
00159 m=m->next;
00160 while(m->down) m=m->down;
00161 *ret = m;
00162 return count;
00163 }
00164 if((m->next == NULL) || (compared<0))
00165 m = m->down, count++;
00166 else
00167 m = m->next, count++;
00168 }
00169 #ifdef SL_DEBUG
00170 printf("Looking -- not found in %d steps\n", count);
00171 #endif
00172 *ret = NULL;
00173 return count;
00174 }
00175 void *skiplist_next(Skiplist *sl, struct skiplistnode **iter) {
00176 if(!*iter) return NULL;
00177 *iter = (*iter)->next;
00178 return (*iter)?((*iter)->data):NULL;
00179 }
00180 void *skiplist_previous(Skiplist *sl, struct skiplistnode **iter) {
00181 if(!*iter) return NULL;
00182 *iter = (*iter)->prev;
00183 return (*iter)?((*iter)->data):NULL;
00184 }
00185 struct skiplistnode *skiplist_insert(Skiplist *sl,
00186 void *data) {
00187 if(!sl->compare) return 0;
00188 return skiplist_insert_compare(sl, data, sl->compare);
00189 }
00190
00191 struct skiplistnode *skiplist_insert_compare(Skiplist *sl,
00192 void *data,
00193 SkiplistComparator comp) {
00194 struct skiplistnode *m, *p, *tmp, *ret, **stack;
00195 int nh=1, ch, stacki;
00196 #ifdef SLDEBUG
00197 skiplist_print_struct(sl, "BI: ");
00198 #endif
00199 if(!sl->top) {
00200 sl->height = 1;
00201 sl->topend = sl->bottomend = sl->top = sl->bottom =
00202 (struct skiplistnode *)malloc(sizeof(struct skiplistnode));
00203 assert(sl->top);
00204 sl->top->next = (struct skiplistnode *) NULL;
00205 sl->top->data = (struct skiplistnode *) NULL;
00206 sl->top->prev =(struct skiplistnode *) NULL;
00207 sl->top->up = (struct skiplistnode *) NULL;
00208 sl->top->down = (struct skiplistnode *) NULL;
00209 sl->top->nextindex= (struct skiplistnode *) NULL;
00210 sl->top->previndex = (struct skiplistnode *) NULL;
00211 sl->top->sl = sl;
00212 }
00213 if(sl->preheight) {
00214 while(nh < sl->preheight && get_b_rand()) nh++;
00215 } else {
00216 while(nh <= sl->height && get_b_rand()) nh++;
00217 }
00218
00219
00220 for(;sl->height<nh;sl->height++) {
00221 sl->top->up =
00222 (struct skiplistnode *)malloc(sizeof(struct skiplistnode));
00223 assert(sl->top->up);
00224 sl->top->up->down = sl->top;
00225 sl->top = sl->topend = sl->top->up;
00226 sl->top->prev = sl->top->next = sl->top->nextindex =
00227 sl->top->previndex = sl->top->up = NULL;
00228 sl->top->data = NULL;
00229 sl->top->sl = sl;
00230 }
00231 ch = sl->height;
00232
00233
00234 m = sl->top;
00235 stack = (struct skiplistnode **)malloc(sizeof(struct skiplistnode *)*(nh));
00236 stacki=0;
00237 while(m) {
00238 int compared=-1;
00239 if(m->next) compared=comp(data, m->next->data);
00240 if(compared == 0) {
00241 free(stack);
00242 return 0;
00243 }
00244 if((m->next == NULL) || (compared<0)) {
00245 if(ch<=nh) {
00246
00247 stack[stacki++] = m;
00248 }
00249 m = m->down;
00250 ch--;
00251 } else {
00252 m = m->next;
00253 }
00254 }
00255
00256 p = NULL;
00257 for(;stacki>0;stacki--) {
00258 m = stack[stacki-1];
00259 tmp = (struct skiplistnode *)malloc(sizeof(struct skiplistnode));
00260 tmp->next = m->next;
00261 if(m->next) m->next->prev=tmp;
00262 tmp->prev = m;
00263 tmp->up = NULL;
00264 tmp->nextindex = tmp->previndex = NULL;
00265 tmp->down = p;
00266 if(p) p->up=tmp;
00267 tmp->data = data;
00268 tmp->sl = sl;
00269 m->next = tmp;
00270
00271 if(!p) ret=tmp;
00272 p = tmp;
00273 }
00274 free(stack);
00275 if(sl->index != NULL) {
00276
00277 struct skiplistnode *p, *ni, *li;
00278 li=ret;
00279 for(p = skiplist_getlist(sl->index); p; skiplist_next(sl->index, &p)) {
00280 ni = skiplist_insert((Skiplist *)p->data, ret->data);
00281 assert(ni);
00282 #ifdef SLDEBUG
00283 fprintf(stderr, "Adding %p to index %p\n", ret->data, p->data);
00284 #endif
00285 li->nextindex = ni;
00286 ni->previndex = li;
00287 li = ni;
00288 }
00289 } else {
00290 sl->size++;
00291 }
00292 #ifdef SLDEBUG
00293 skiplist_print_struct(sl, "AI: ");
00294 #endif
00295 return ret;
00296 }
00297 struct skiplistnode *skiplist_append(Skiplist *sl, void *data) {
00298 int nh=1, ch, compared;
00299 struct skiplistnode *lastnode, *nodeago;
00300 if(sl->bottomend != sl->bottom) {
00301 compared=sl->compare(data, sl->bottomend->prev->data);
00302
00303 if(compared<=0) return NULL;
00304 }
00305 if(sl->preheight) {
00306 while(nh < sl->preheight && get_b_rand()) nh++;
00307 } else {
00308 while(nh <= sl->height && get_b_rand()) nh++;
00309 }
00310
00311
00312 lastnode = sl->bottomend;
00313 nodeago = NULL;
00314
00315 if(!lastnode) return skiplist_insert(sl, data);
00316
00317 for(;sl->height<nh;sl->height++) {
00318 sl->top->up =
00319 (struct skiplistnode *)malloc(sizeof(struct skiplistnode));
00320 assert(sl->top);
00321 sl->top->up->down = sl->top;
00322 sl->top = sl->top->up;
00323 sl->top->prev = sl->top->next = sl->top->nextindex =
00324 sl->top->previndex = NULL;
00325 sl->top->data = NULL;
00326 sl->top->sl = sl;
00327 }
00328 ch = sl->height;
00329 while(nh) {
00330 struct skiplistnode *anode;
00331 anode =
00332 (struct skiplistnode *)malloc(sizeof(struct skiplistnode));
00333 anode->next = lastnode;
00334 anode->prev = lastnode->prev;
00335 anode->up = NULL;
00336 anode->down = nodeago;
00337 if(lastnode->prev) {
00338 if(lastnode == sl->bottom)
00339 sl->bottom = anode;
00340 else if (lastnode == sl->top)
00341 sl->top = anode;
00342 }
00343 nodeago = anode;
00344 lastnode = lastnode->up;
00345 nh--;
00346 }
00347 sl->size++;
00348 return sl->bottomend;
00349 }
00350 Skiplist *skiplist_concat(Skiplist *sl1, Skiplist *sl2) {
00351
00352 int compared, eheight;
00353 Skiplist temp;
00354 struct skiplistnode *lbottom, *lbottomend, *b1, *e1, *b2, *e2;
00355 if(sl1->bottomend == NULL || sl1->bottomend->prev == NULL) {
00356 skiplist_remove_all(sl1, free);
00357 temp = *sl1;
00358 *sl1 = *sl2;
00359 *sl2 = temp;
00360
00361 return sl1;
00362 }
00363 if(sl2->bottom == NULL || sl2->bottom->next == NULL) {
00364 skiplist_remove_all(sl2, free);
00365 return sl1;
00366 }
00367 compared = sl1->compare(sl1->bottomend->prev->data, sl2->bottom->data);
00368
00369 if(compared<=0) return NULL;
00370
00371
00372 lbottom = lbottomend = NULL;
00373 eheight = MIN(sl1->height, sl2->height);
00374 b1 = sl1->bottom; e1 = sl1->bottomend;
00375 b2 = sl2->bottom; e2 = sl2->bottomend;
00376 while(eheight) {
00377 e1->prev->next = b2;
00378 b2->prev = e1->prev->next;
00379 e2->prev->next = e1;
00380 e1->prev = e2->prev;
00381 e2->prev = NULL;
00382 b2 = e2;
00383 b1->down = lbottom;
00384 e1->down = lbottomend;
00385 if(lbottom) lbottom->up = b1;
00386 if(lbottomend) lbottomend->up = e1;
00387
00388 lbottom = b1;
00389 lbottomend = e1;
00390 }
00391
00392 if(sl2->height > sl1->height) {
00393 b1->up = b2->up;
00394 e1->up = e2->up;
00395 b1->up->down = b1;
00396 e1->up->down = e1;
00397 sl1->height = sl2->height;
00398 sl1->top = sl2->top;
00399 sl1->topend = sl2->topend;
00400 }
00401
00402
00403 sl2->top = sl2->topend = b2;
00404 sl2->top->up = NULL;
00405 sl1->size += sl2->size;
00406 skiplist_remove_all(sl2, free);
00407 return sl1;
00408 }
00409 int skiplist_remove(Skiplist *sl,
00410 void *data, FreeFunc myfree) {
00411 if(!sl->compare) return 0;
00412 return skiplist_remove_compare(sl, data, myfree, sl->comparek);
00413 }
00414 void skiplist_print_struct(Skiplist *sl, char *prefix) {
00415 struct skiplistnode *p, *q;
00416 fprintf(stderr, "Skiplist Structure (height: %d)\n", sl->height);
00417 p = sl->bottom;
00418 while(p) {
00419 q = p;
00420 fprintf(stderr, prefix);
00421 while(q) {
00422 fprintf(stderr, "%p ", q->data);
00423 q=q->up;
00424 }
00425 fprintf(stderr, "\n");
00426 p=p->next;
00427 }
00428 }
00429 int skiplisti_remove(Skiplist *sl, struct skiplistnode *m, FreeFunc myfree) {
00430 struct skiplistnode *p;
00431 if(!m) return 0;
00432 if(m->nextindex) skiplisti_remove(m->nextindex->sl, m->nextindex, NULL);
00433 else sl->size--;
00434 #ifdef SLDEBUG
00435 skiplist_print_struct(sl, "BR:");
00436 #endif
00437 while(m->up) m=m->up;
00438 while(m) {
00439 p=m;
00440 p->prev->next = p->next;
00441 if(p->next) p->next->prev = p->prev;
00442 m=m->down;
00443
00444 if(!m && myfree && p->data) myfree(p->data);
00445 free(p);
00446 }
00447 while(sl->top && sl->top->next == NULL) {
00448
00449 p = sl->top;
00450 sl->top = sl->top->down;
00451 if(sl->top) sl->top->up = NULL;
00452 free(p);
00453 sl->height--;
00454 }
00455 if(!sl->top) sl->bottom = NULL;
00456 assert(sl->height>=0);
00457 #ifdef SLDEBUG
00458 skiplist_print_struct(sl, "AR: ");
00459 #endif
00460 return sl->height;
00461 }
00462 int skiplist_remove_compare(Skiplist *sli,
00463 void *data,
00464 FreeFunc myfree, SkiplistComparator comp) {
00465 struct skiplistnode *m;
00466 Skiplist *sl;
00467 if(comp==sli->comparek || !sli->index) {
00468 sl = sli;
00469 } else {
00470 skiplist_find(sli->index, (void *)comp, &m);
00471 assert(m);
00472 sl= (Skiplist *) m->data;
00473 }
00474 skiplisti_find_compare(sl, data, &m, comp);
00475 if(!m) return 0;
00476 while(m->previndex) m=m->previndex;
00477 return skiplisti_remove(sl, m, myfree);
00478 }
00479 void skiplist_remove_all(Skiplist *sl, FreeFunc myfree) {
00480
00481
00482
00483 struct skiplistnode *m, *p, *u;
00484 m=sl->bottom;
00485 while(m) {
00486 p = m->next;
00487 if(myfree && p->data) myfree(p->data);
00488 while(m) {
00489 u = m->up;
00490 free(m);
00491 m=u;
00492 }
00493 m = p;
00494 }
00495 sl->top = sl->bottom = NULL;
00496 sl->height = 0;
00497 sl->size = 0;
00498 }
00499
00500 void *skiplist_pop(Skiplist * a, FreeFunc myfree)
00501 {
00502 struct skiplistnode *sln;
00503 void *data = NULL;
00504 sln = skiplist_getlist(a);
00505 if (sln) {
00506 data = sln->data;
00507 skiplisti_remove(a, sln, myfree);
00508 }
00509 return data;
00510 }