Staging
v0.5.1
https://github.com/python/cpython
Revision 62a14db9f4f7b77bfc5663902f0d05f74901e950 authored by R. David Murray on 26 June 2010, 18:39:50 UTC, committed by R. David Murray on 26 June 2010, 18:39:50 UTC
In 2.5 the email version was bumped to 4.0.2 just before release but
after the maintenance branch was set up.  The bump was not backported
to trunk, and 2.6 went out the door with a version number of 4.0.1.
I bumped this to 4.0.2 because of a behavior change, but that makes
it look the same as 2.5.  So bump it again to 4.0.3.
1 parent 04a3439
Raw File
Tip revision: 62a14db9f4f7b77bfc5663902f0d05f74901e950 authored by R. David Murray on 26 June 2010, 18:39:50 UTC
#9085: email versions have gotten out of sync, 2.7 is actually 4.0.3.
Tip revision: 62a14db
rotatingtree.c
#include "rotatingtree.h"

#define KEY_LOWER_THAN(key1, key2)  ((char*)(key1) < (char*)(key2))

/* The randombits() function below is a fast-and-dirty generator that
 * is probably irregular enough for our purposes.  Note that it's biased:
 * I think that ones are slightly more probable than zeroes.  It's not
 * important here, though.
 */

static unsigned int random_value = 1;
static unsigned int random_stream = 0;

static int
randombits(int bits)
{
    int result;
    if (random_stream < (1U << bits)) {
        random_value *= 1082527;
        random_stream = random_value;
    }
    result = random_stream & ((1<<bits)-1);
    random_stream >>= bits;
    return result;
}


/* Insert a new node into the tree.
   (*root) is modified to point to the new root. */
void
RotatingTree_Add(rotating_node_t **root, rotating_node_t *node)
{
    while (*root != NULL) {
        if (KEY_LOWER_THAN(node->key, (*root)->key))
            root = &((*root)->left);
        else
            root = &((*root)->right);
    }
    node->left = NULL;
    node->right = NULL;
    *root = node;
}

/* Locate the node with the given key.  This is the most complicated
   function because it occasionally rebalances the tree to move the
   resulting node closer to the root. */
rotating_node_t *
RotatingTree_Get(rotating_node_t **root, void *key)
{
    if (randombits(3) != 4) {
        /* Fast path, no rebalancing */
        rotating_node_t *node = *root;
        while (node != NULL) {
            if (node->key == key)
                return node;
            if (KEY_LOWER_THAN(key, node->key))
                node = node->left;
            else
                node = node->right;
        }
        return NULL;
    }
    else {
        rotating_node_t **pnode = root;
        rotating_node_t *node = *pnode;
        rotating_node_t *next;
        int rotate;
        if (node == NULL)
            return NULL;
        while (1) {
            if (node->key == key)
                return node;
            rotate = !randombits(1);
            if (KEY_LOWER_THAN(key, node->key)) {
                next = node->left;
                if (next == NULL)
                    return NULL;
                if (rotate) {
                    node->left = next->right;
                    next->right = node;
                    *pnode = next;
                }
                else
                    pnode = &(node->left);
            }
            else {
                next = node->right;
                if (next == NULL)
                    return NULL;
                if (rotate) {
                    node->right = next->left;
                    next->left = node;
                    *pnode = next;
                }
                else
                    pnode = &(node->right);
            }
            node = next;
        }
    }
}

/* Enumerate all nodes in the tree.  The callback enumfn() should return
   zero to continue the enumeration, or non-zero to interrupt it.
   A non-zero value is directly returned by RotatingTree_Enum(). */
int
RotatingTree_Enum(rotating_node_t *root, rotating_tree_enum_fn enumfn,
                  void *arg)
{
    int result;
    rotating_node_t *node;
    while (root != NULL) {
        result = RotatingTree_Enum(root->left, enumfn, arg);
        if (result != 0) return result;
        node = root->right;
        result = enumfn(root, arg);
        if (result != 0) return result;
        root = node;
    }
    return 0;
}
back to top