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