home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
unix
/
volume26
/
philspell-1.0
/
part01
/
skiplist.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-05-01
|
4KB
|
139 lines
/*
* Skiplist library COPYRIGHT (c) 1992, 1991, 1990, 1989, 1988, 1987 by
* Phillip "Edward" Nunez. I wrote all this stuff and had it copyrighted
* and don't let anyone ever tell you any different!
*
*/
#include <stdio.h>
#include <assert.h>
#include "skiplist.h"
#define PROBABILITY 4
/*
* The definition of PROBABILITY determines how many pointers per node an
* element of a skiplist has. A PROBABILITY of 4 means each node will have
* (3/4)1 + (1/4)(3/4)2 + (1/4)(1/4)(3/4)3... ~~ 1.31 pointers per node.
* A PROBABILITY of 5 yields (4/5)1 + (1/5)(4/5)2... ~~ 1.24 p/node.
*/
#define RANDOM rand
/*
* The RANDOM function you define here should be seeded in your main program.
*/
/*
* skip_create creates the header node for a skiplist. The pointer to this
* node is what you should use to refer to the skiplist. The argument 'max'
* determines the maximum height of any node in the skiplist; the head is
* always this high. Skiplists can store on the order of 2^n elements
* efficiently where n is that maximum height.
*/
skipnode skip_create(int max) {
skipnode newnode;
int i;
newnode = (skipnode)malloc(sizeof(struct skipnode) + sizeof(skipnode) * max);
assert(newnode != NULL);
newnode->name = "";
newnode->ptr = NULL;
for (i = 0; i <= max; i++) newnode->next[i] = newnode;
return newnode;
}
/*
* skip_add adds an item to the skiplist. 'name' is the name (key)
* to the data; 'ptr' is the data; level is the maximum level (the same
* as used in the call to skip_create) and 'node' is the skiplist you're
* looking things up in.
*
* The 'name' parameter must have been allocated with 'malloc' or somesimilar.
* It will be freed when the node disappears.
*/
void skip_add(char *name, void *ptr, skipnode node, int level) {
skipnode newnode;
int size, newlevel;
newlevel = 0;
while (RANDOM() % PROBABILITY) newlevel++;
if (newlevel > level) newlevel = level;
size = sizeof(struct skipnode) + sizeof(skipnode) * newlevel;
newnode = (skipnode)malloc(size);
newnode->name = name;
newnode->ptr = ptr;
while (level >= 0) {
while (strcasecmp(name, node->next[level]->name) < 0)
node = node->next[level];
if (level <= newlevel) {
newnode->next[level] = node->next[level];
node->next[level] = newnode;
}
level--;
}
}
/*
* skip_lookup: Given the name of the data, the skiplist, the
* max level, and the default to return if the data cannot be found,
* look up the data in the list.
*/
void *skip_lookup(char *name, skipnode node, int level, void *def) {
int d;
while (level >= 0) {
while ((d = strcasecmp(name, node->next[level]->name)) < 0)
node = node->next[level];
if (!d) return node->next[level]->ptr;
level--;
}
return def;
}
/*
* skip_remove: remove a skipnode from a the skiplist given. 'name'
* is the key, 'level' is the max level.
*/
void skip_remove(char *name, skipnode node, int level) {
int cmpsav;
skipnode n;
while (level >= 0) {
while ((cmpsav = strcasecmp(name, node->next[level]->name)) < 0)
node = node->next[level];
if (cmpsav == 0)
n = node->next[level];
node->next[level] = node->next[level]->next[level];
level--;
}
free(n->name);
free(n);
}
/*
* skip_free: free an entire skiplist.
*/
void skip_free(skipnode node) {
skipnode m, n = node->next[0];
while (n != node) {
free(n->name);
m = n->next[0];
free(n);
n = m;
}
free(node);
}