File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / lighttpd / src / splaytree.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Oct 14 10:32:47 2013 UTC (10 years, 8 months ago) by misho
Branches: lighttpd, MAIN
CVS tags: v1_4_41p8, v1_4_35p0, v1_4_35, v1_4_33, HEAD
1.4.33

    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>