v13i107: C implementation of skip lists (Comm. of the ACM, June 1990)
Bill Pugh
pugh at cs.UMD.EDU
Tue Jul 10 08:54:01 AEST 1990
Posting-number: Volume 13, Issue 107
Submitted-by: pugh at cs.UMD.EDU (Bill Pugh)
Archive-name: skiplists/part01
The following is a C implementation of skip lists, as described in the
June 1990 issue of the Communications of the ACM. Skip lists are
a simple and efficient alternative to balanced trees. A Pascal implementation
is also available from the author or by anonymous ftp from mimsy.cs.umd.edu.
Bill Pugh
pugh at cs.umd.edu
-----
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of shell archive."
# Contents: skipLists.c
# Wrapped by pugh at cs.umd.edu on Mon Jul 1 20:00:00 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'skipLists.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'skipLists.c'\"
else
echo shar: Extracting \"'skipLists.c'\" \(5876 characters\)
sed "s/^X//" >'skipLists.c' <<'END_OF_FILE'
X/*
X
XExample of Skip List source code for C:
X
XSkip Lists are a probabilistic alternative to balanced trees, as
Xdescribed in the June 1990 issue of CACM and were invented by
XWilliam Pugh in 1987.
X
XThe author can be contacted at pugh at cs.umd.edu
X
XThis file contains source code to implement a dictionary using
Xskip lists and a test driver to test the routines.
X
XA couple of comments about this implementation:
X The routine randomLevel has been hard-coded to generate random
X levels using p=0.25. It can be easily changed.
X
X The insertion routine has been implemented so as to use the
X dirty hack described in the CACM paper: if a random level is
X generated that is more than the current maximum level, the
X current maximum level plus one is used instead.
X
X Levels start at zero and go up to MaxLevel (which is equal to
X (MaxNumberOfLevels-1).
X
XThe compile flag allowDuplicates determines whether or not duplicates
Xare allowed. If defined, duplicates are allowed and act in a FIFO manner.
XIf not defined, an insertion of a value already in the file updates the
Xpreviously existing binding.
X
XBitsInRandom is defined to be the number of bits returned by a call to
Xrandom(). For most all machines with 32-bit integers, this is 31 bits
Xas currently set.
X
XThe routines defined in this file are:
X
X init: defines NIL and initializes the random bit source
X
X newList: returns a new, empty list
X
X freeList(l): deallocates the list l (along with any elements in l)
X
X randomLevel: Returns a random level
X
X insert(l,key,value): inserts the binding (key,value) into l. If
X allowDuplicates is undefined, returns true if key was newly
X inserted into the list, false if key already existed
X
X delete(l,key): deletes any binding of key from the l. Returns
X false if key was not defined.
X
X search(l,key,&value): Searches for key in l and returns true if found.
X If found, the value associated with key is stored in the
X location pointed to by &value
X
X*/
X
X
X#define false 0
X#define true 1
Xtypedef char boolean;
X#define BitsInRandom 31
X
X#define allowDuplicates
X
X#define MaxNumberOfLevels 16
X#define MaxLevel (MaxNumberOfLevels-1)
X#define newNodeOfLevel(l) (node)malloc(sizeof(struct nodeStructure)+(l)*sizeof(node *))
X
Xtypedef int keyType;
Xtypedef int valueType;
X
X#ifdef allowDuplicates
Xboolean delete(), search();
Xvoid insert();
X#else
Xboolean insert(), delete(), search();
X#endif
X
Xtypedef struct nodeStructure *node;
X
Xtypedef struct nodeStructure{
X keyType key;
X valueType value;
X node forward[1]; /* variable sized array of forward pointers */
X };
X
Xtypedef struct listStructure{
X int level; /* Maximum level of the list
X (1 more than the number of levels in the list) */
X struct nodeStructure * header; /* pointer to header */
X } * list;
X
Xnode NIL;
X
Xint randomsLeft;
Xint randomBits;
X
Xinit() {
X NIL = newNodeOfLevel(0);
X NIL->key = 0x7fffffff;
X randomBits = random();
X randomsLeft = BitsInRandom/2;
X};
X
Xlist newList() {
X list l;
X int i;
X
X l = (list)malloc(sizeof(struct listStructure));
X l->level = 0;
X l->header = newNodeOfLevel(MaxNumberOfLevels);
X for(i=0;i<MaxNumberOfLevels;i++) l->header->forward[i] = NIL;
X return(l);
X };
X
XfreeList(l)
X list l;
X {
X register node p,q;
X p = l->header;
X do {
X q = p->forward[0];
X free(p);
X p = q; }
X while (p!=NIL);
X free(l);
X };
X
Xint randomLevel()
X {register int level = 0;
X register int b;
X do {
X b = randomBits&3;
X if (!b) level++;
X randomBits>>=2;
X if (--randomsLeft == 0) {
X randomBits = random();
X randomsLeft = BitsInRandom/2;
X };
X } while (!b);
X return(level>MaxLevel ? MaxLevel : level);
X };
X
X#ifdef allowDuplicates
Xvoid insert(l,key,value)
X#else
Xboolean insert(l,key,value)
X#endif
X
Xregister list l;
Xregister keyType key;
Xregister valueType value;
X {
X register int k;
X node update[MaxNumberOfLevels];
X register node p,q;
X
X p = l->header;
X k = l->level;
X do {
X while (q = p->forward[k], q->key < key) p = q;
X update[k] = p;
X } while(--k>=0);
X
X#ifndef allowDuplicates
X if (q->key == key) {
X q->value = value;
X return(false);
X };
X#endif
X
X k = randomLevel();
X if (k>l->level) {
X k = ++l->level;
X update[k] = l->header;
X };
X q = newNodeOfLevel(k);
X q->key = key;
X q->value = value;
X do {
X p = update[k];
X q->forward[k] = p->forward[k];
X p->forward[k] = q;
X } while(--k>=0);
X#ifndef allowDuplicates
X return(true);
X#endif
X }
X
Xboolean delete(l,key)
Xregister list l;
Xregister keyType key;
X {
X register int k,m;
X node update[MaxNumberOfLevels];
X register node p,q;
X
X p = l->header;
X k = m = l->level;
X do {
X while (q = p->forward[k], q->key < key) p = q;
X update[k] = p;
X } while(--k>=0);
X
X if (q->key == key) {
X for(k=0; k<=m && (p=update[k])->forward[k] == q; k++)
X p->forward[k] = q->forward[k];
X free(q);
X while( l->header->forward[m] == NIL && m > 0 )
X m--;
X l->level = m;
X return(true);
X }
X else return(false);
X }
X
Xboolean search(l,key,valuePointer)
Xregister list l;
Xregister keyType key;
XvalueType * valuePointer;
X {
X register int k;
X register node p,q;
X p = l->header;
X k = l->level;
X do while (q = p->forward[k], q->key < key) p = q;
X while (--k>=0);
X if (q->key != key) return(false);
X *valuePointer = q->value;
X return(true);
X };
X
X#define sampleSize 65536
Xmain() {
X list l;
X register int i,k;
X keyType keys[sampleSize];
X valueType v;
X
X init();
X
X l= newList();
X
X for(k=0;k<sampleSize;k++) {
X keys[k]=random();
X insert(l,keys[k],keys[k]);
X };
X
X
X for(i=0;i<4;i++) {
X for(k=0;k<sampleSize;k++) {
X if (!search(l,keys[k],&v)) printf("error in search #%d,#%d\n",i,k);
X if (v != keys[k]) printf("search returned wrong value\n");
X };
X for(k=0;k<sampleSize;k++) {
X if (! delete(l,keys[k])) printf("error in delete\n");
X keys[k] = random();
X insert(l,keys[k],keys[k]);
X };
X };
X
X freeList(l);
X
X };
END_OF_FILE
if test 5876 -ne `wc -c <'skipLists.c'`; then
echo shar: \"'skipLists.c'\" unpacked with wrong size!
fi
fi
echo shar: End of shell archive
exit 0
More information about the Comp.sources.misc
mailing list