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>