Annotation of embedaddon/lighttpd/src/splaytree.c, revision 1.1
1.1 ! misho 1: /*
! 2: An implementation of top-down splaying with sizes
! 3: D. Sleator <sleator@cs.cmu.edu>, January 1994.
! 4:
! 5: This extends top-down-splay.c to maintain a size field in each node.
! 6: This is the number of nodes in the subtree rooted there. This makes
! 7: it possible to efficiently compute the rank of a key. (The rank is
! 8: the number of nodes to the left of the given key.) It it also
! 9: possible to quickly find the node of a given rank. Both of these
! 10: operations are illustrated in the code below. The remainder of this
! 11: introduction is taken from top-down-splay.c.
! 12:
! 13: "Splay trees", or "self-adjusting search trees" are a simple and
! 14: efficient data structure for storing an ordered set. The data
! 15: structure consists of a binary tree, with no additional fields. It
! 16: allows searching, insertion, deletion, deletemin, deletemax,
! 17: splitting, joining, and many other operations, all with amortized
! 18: logarithmic performance. Since the trees adapt to the sequence of
! 19: requests, their performance on real access patterns is typically even
! 20: better. Splay trees are described in a number of texts and papers
! 21: [1,2,3,4].
! 22:
! 23: The code here is adapted from simple top-down splay, at the bottom of
! 24: page 669 of [2]. It can be obtained via anonymous ftp from
! 25: spade.pc.cs.cmu.edu in directory /usr/sleator/public.
! 26:
! 27: The chief modification here is that the splay operation works even if the
! 28: item being splayed is not in the tree, and even if the tree root of the
! 29: tree is NULL. So the line:
! 30:
! 31: t = splay(i, t);
! 32:
! 33: causes it to search for item with key i in the tree rooted at t. If it's
! 34: there, it is splayed to the root. If it isn't there, then the node put
! 35: at the root is the last one before NULL that would have been reached in a
! 36: normal binary search for i. (It's a neighbor of i in the tree.) This
! 37: allows many other operations to be easily implemented, as shown below.
! 38:
! 39: [1] "Data Structures and Their Algorithms", Lewis and Denenberg,
! 40: Harper Collins, 1991, pp 243-251.
! 41: [2] "Self-adjusting Binary Search Trees" Sleator and Tarjan,
! 42: JACM Volume 32, No 3, July 1985, pp 652-686.
! 43: [3] "Data Structure and Algorithm Analysis", Mark Weiss,
! 44: Benjamin Cummins, 1992, pp 119-130.
! 45: [4] "Data Structures, Algorithms, and Performance", Derick Wood,
! 46: Addison-Wesley, 1993, pp 367-375
! 47: */
! 48:
! 49: #include "splaytree.h"
! 50: #include <stdlib.h>
! 51: #include <assert.h>
! 52:
! 53: #define compare(i,j) ((i)-(j))
! 54: /* This is the comparison. */
! 55: /* Returns <0 if i<j, =0 if i=j, and >0 if i>j */
! 56:
! 57: #define node_size splaytree_size
! 58:
! 59: /* Splay using the key i (which may or may not be in the tree.)
! 60: * The starting root is t, and the tree used is defined by rat
! 61: * size fields are maintained */
! 62: splay_tree * splaytree_splay (splay_tree *t, int i) {
! 63: splay_tree N, *l, *r, *y;
! 64: int comp, l_size, r_size;
! 65:
! 66: if (t == NULL) return t;
! 67: N.left = N.right = NULL;
! 68: l = r = &N;
! 69: l_size = r_size = 0;
! 70:
! 71: for (;;) {
! 72: comp = compare(i, t->key);
! 73: if (comp < 0) {
! 74: if (t->left == NULL) break;
! 75: if (compare(i, t->left->key) < 0) {
! 76: y = t->left; /* rotate right */
! 77: t->left = y->right;
! 78: y->right = t;
! 79: t->size = node_size(t->left) + node_size(t->right) + 1;
! 80: t = y;
! 81: if (t->left == NULL) break;
! 82: }
! 83: r->left = t; /* link right */
! 84: r = t;
! 85: t = t->left;
! 86: r_size += 1+node_size(r->right);
! 87: } else if (comp > 0) {
! 88: if (t->right == NULL) break;
! 89: if (compare(i, t->right->key) > 0) {
! 90: y = t->right; /* rotate left */
! 91: t->right = y->left;
! 92: y->left = t;
! 93: t->size = node_size(t->left) + node_size(t->right) + 1;
! 94: t = y;
! 95: if (t->right == NULL) break;
! 96: }
! 97: l->right = t; /* link left */
! 98: l = t;
! 99: t = t->right;
! 100: l_size += 1+node_size(l->left);
! 101: } else {
! 102: break;
! 103: }
! 104: }
! 105: l_size += node_size(t->left); /* Now l_size and r_size are the sizes of */
! 106: r_size += node_size(t->right); /* the left and right trees we just built.*/
! 107: t->size = l_size + r_size + 1;
! 108:
! 109: l->right = r->left = NULL;
! 110:
! 111: /* The following two loops correct the size fields of the right path */
! 112: /* from the left child of the root and the right path from the left */
! 113: /* child of the root. */
! 114: for (y = N.right; y != NULL; y = y->right) {
! 115: y->size = l_size;
! 116: l_size -= 1+node_size(y->left);
! 117: }
! 118: for (y = N.left; y != NULL; y = y->left) {
! 119: y->size = r_size;
! 120: r_size -= 1+node_size(y->right);
! 121: }
! 122:
! 123: l->right = t->left; /* assemble */
! 124: r->left = t->right;
! 125: t->left = N.right;
! 126: t->right = N.left;
! 127:
! 128: return t;
! 129: }
! 130:
! 131: splay_tree * splaytree_insert(splay_tree * t, int i, void *data) {
! 132: /* Insert key i into the tree t, if it is not already there. */
! 133: /* Return a pointer to the resulting tree. */
! 134: splay_tree * new;
! 135:
! 136: if (t != NULL) {
! 137: t = splaytree_splay(t, i);
! 138: if (compare(i, t->key)==0) {
! 139: return t; /* it's already there */
! 140: }
! 141: }
! 142: new = (splay_tree *) malloc (sizeof (splay_tree));
! 143: assert(new);
! 144: if (t == NULL) {
! 145: new->left = new->right = NULL;
! 146: } else if (compare(i, t->key) < 0) {
! 147: new->left = t->left;
! 148: new->right = t;
! 149: t->left = NULL;
! 150: t->size = 1+node_size(t->right);
! 151: } else {
! 152: new->right = t->right;
! 153: new->left = t;
! 154: t->right = NULL;
! 155: t->size = 1+node_size(t->left);
! 156: }
! 157: new->key = i;
! 158: new->data = data;
! 159: new->size = 1 + node_size(new->left) + node_size(new->right);
! 160: return new;
! 161: }
! 162:
! 163: splay_tree * splaytree_delete(splay_tree *t, int i) {
! 164: /* Deletes i from the tree if it's there. */
! 165: /* Return a pointer to the resulting tree. */
! 166: splay_tree * x;
! 167: int tsize;
! 168:
! 169: if (t==NULL) return NULL;
! 170: tsize = t->size;
! 171: t = splaytree_splay(t, i);
! 172: if (compare(i, t->key) == 0) { /* found it */
! 173: if (t->left == NULL) {
! 174: x = t->right;
! 175: } else {
! 176: x = splaytree_splay(t->left, i);
! 177: x->right = t->right;
! 178: }
! 179: free(t);
! 180: if (x != NULL) {
! 181: x->size = tsize-1;
! 182: }
! 183: return x;
! 184: } else {
! 185: return t; /* It wasn't there */
! 186: }
! 187: }
! 188:
! 189: #if 0
! 190: static splay_tree *find_rank(int r, splay_tree *t) {
! 191: /* Returns a pointer to the node in the tree with the given rank. */
! 192: /* Returns NULL if there is no such node. */
! 193: /* Does not change the tree. To guarantee logarithmic behavior, */
! 194: /* the node found here should be splayed to the root. */
! 195: int lsize;
! 196: if ((r < 0) || (r >= node_size(t))) return NULL;
! 197: for (;;) {
! 198: lsize = node_size(t->left);
! 199: if (r < lsize) {
! 200: t = t->left;
! 201: } else if (r > lsize) {
! 202: r = r - lsize -1;
! 203: t = t->right;
! 204: } else {
! 205: return t;
! 206: }
! 207: }
! 208: }
! 209: #endif
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>