/* Example of Skip List source code for C: Skip Lists are a probabilistic alternative to balanced trees, as described in the June 1990 issue of CACM and were invented by William Pugh in 1987. This file contains source code to implement a dictionary using skip lists and a test driver to test the routines. A couple of comments about this implementation: The routine randomLevel has been hard-coded to generate random levels using p=0.25. It can be easily changed. The insertion routine has been implemented so as to use the dirty hack described in the CACM paper: if a random level is generated that is more than the current maximum level, the current maximum level plus one is used instead. Levels start at zero and go up to MaxLevel (which is equal to (MaxNumberOfLevels-1). The compile flag allowDuplicates determines whether or not duplicates are allowed. If defined, duplicates are allowed and act in a FIFO manner. If not defined, an insertion of a value already in the file updates the previously existing binding. BitsInRandom is defined to be the number of bits returned by a call to random(). For most all machines with 32-bit integers, this is 31 bits as currently set. */ #include #include "list.h" node NIL; int randomsLeft; int randomBits; /* init - defines NIL and initializes the random bit source */ init() { char *ckalloc(); NIL = newNodeOfLevel(0); NIL->key = 0x7fffffff; NIL->value = NULL; NIL->forward[0] = NIL; randomBits = random(); randomsLeft = BitsInRandom/2; } /* newList - create a new list */ list newList() { list l; int i; char *ckalloc(); l = (list)ckalloc(sizeof(struct listStructure)); l->level = 0; l->header = newNodeOfLevel(MaxNumberOfLevels); l->header->key = -1; l->header->value = NULL; for(i=0;iheader->forward[i] = NIL; return(l); } /* unewList - create a new list */ ulist unewList() { ulist l; char *ckalloc(); l = (ulist)ckalloc(sizeof(struct ulistStructure)); l->header = (unode)ckalloc(sizeof(struct unodeStructure)); l->header->key = -1; l->header->link = NULL; return(l); } /* reset_pos - reset cur_p */ void reset_pos(list l) { register int k; register node p; p = l->header; for (k = 0; k <= l->level; ++k) l->update[k] = p; } /* sreset_pos - reset l->update[0] */ sreset_pos(list l) { l->update[0] = l->header; } /* freeList - free the space of the list */ void freeList(list l) { register node p,q; register int i=0; p = l->header; do { ++i; q = p->forward[0]; decre(p->value); free(p); p = q; } while (p!=NIL); free(l); } /* randomLevel - return a random level */ int randomLevel(int maxl) {register int level = 0; register int b; do { b = randomBits&3; if (!b) level++; randomBits>>=2; if (--randomsLeft == 0) { randomBits = random(); randomsLeft = BitsInRandom/2; }; } while (!b); return(level>maxl ? maxl : level); } /* uinsert - insert a new node to the ulist */ void uinsert(ulist l, keyType key) { register unode p,q; char *ckalloc(); for (p=l->header,q=p->link; q && q->keylink); q = (unode)ckalloc(sizeof(struct unodeStructure)); q->key = key; q->link = p->link; p->link = q; } /* delete - delete a node from the list by key */ int delete(list l, keyType key) { register int k,m; register node p,q; p = l->header; k = m = l->level; do { while (q = p->forward[k], q->key < key) p = q; l->update[k] = p; } while(--k>=0); if (q->key == key) { for(k=0; k<=m && (p=l->update[k])->forward[k] == q; k++) p->forward[k] = q->forward[k]; free(q); while( l->header->forward[m] == NIL && m > 0 ) m--; l->level = m; return(true); } else return(false); } /* usearch - search a node in the ulist by key */ boolean usearch(ulist l, keyType key) { register unode p; if (!l) return(false); for (p=l->header; p && p->key < key; p=p->link); if (p && p->key == key) return(true); else return(false); } /* rsearch - search a node in the list by key */ /* find p s.t. p->key < key <= (p->forward[0])->key */ valueType rsearch(list l, keyType key) { register int k; register node p,q; p = l->header; k = l->level; do { while (q = p->forward[k], q->key < key) p = q; l->update[k] = p; } while(--k>=0); return(p->value); } /* rsearch_next - search from cur_p */ /* find p s.t. p->key < key <= (p->forward[0])->key */ valueType rsearch_next(list l, keyType key) { register int k; register node p,q; k = l->level; p = l->update[k]; do { while (q = p->forward[k] , q->key < key) p = q; l->update[k] = p; } while(--k>=0); return(p->value); } /* cur_key - return the key of the node pointed by the pointer cur_p */ keyType cur_key(list l) { return((l->update[0])->key); } /* update_node - update the value of the node pointed by cur_p */ void update_node(list l, valueType value) { (l->update[0])->value = value; } /* next_key - return the key of the node next to the node pointed by cur_p */ keyType next_key(list l) { node p; p = (l->update[0])->forward[0]; if (p != NIL) return(p->key); else return(-1); } /* next_val - return the value of the node next to the node pointed by cur_p */ valueType next_val(list l) { node p; p = (l->update[0])->forward[0]; if (p != NIL) return(p->value); else return(NULL); } /* next - move l->cur_p right */ next(list l) { node p, q; int k; p = l->update[0]; q = p->forward[0]; if (q == NIL) return (NULL); else { for (k = 0; k <= l->level && (((l->update[k])->forward[k]) == q); k++) l->update[k] = q; } } /* snext - move l->update[0] right */ valueType snext(list l) { node p, q; int k; p = l->update[0]; q = p->forward[0]; l->update[0] = q; return(q->value); } /*delete_next - delete the node next to the node pointed by cur_p */ void delete_next(list l) { register int k,m; register node p,q; m = l->level; q = (l->update[0])->forward[0]; if (q == NIL) return; for (k=0; k<=m && (p=l->update[k])->forward[k] == q; k++) p->forward[k] = q->forward[k]; free(q); while (l->header->forward[m] == NIL && m > 0) m--; l->level = m; } /* insert_next - insert a new node next to the node pointed by cur_p */ void insert_next(list l, keyType key, valueType value) { register int k; register node p,q; char *ckalloc(); k = randomLevel(MaxLevel); if (k>l->level) { k = ++l->level; l->update[k] = l->header; } q = newNodeOfLevel(k); q->key = key; q->value = value; do { p = l->update[k]; q->forward[k] = p->forward[k]; p->forward[k] = q; l->update[k] = q; } while (--k >= 0); } print(list l) { node p; int i,j,k; valueType v; int rd; printf("************\n"); for (p = (l->header)->forward[0]; p != NIL; p = p->forward[0]) { v=p->value; if (v) printf("%6d %6d %6d \n",v->i,v->j,v->k); } } active_print(list l,int row, int g, int h, int r) { node p; int i,j,k; valueType v; int rd; i=0; j=0; k=0; printf("row = %d\n",row); for (p = (l->header)->forward[0]; p != NIL; p = p->forward[0]) { ++k; v=p->value; if (v) { ++j; printf("%6d %6d %6d %6d %6d",v->i,v->j,v->k,(v->j)-(v->i),v->score); rd = row-(v->i+v->k-1); if (v->score-rd*r <= 0) { ++i; printf(" NOT ACTIVE\n"); } else printf("\n"); } } printf("Number of elements in the list is %d\n",k); printf("Number of fragments in the list is %d\n",j); printf("Number of inactive fragments is %d\n\n",i); }