Python-2.7.3/Modules/rotatingtree.c

No issues found

  1 #include "rotatingtree.h"
  2 
  3 #define KEY_LOWER_THAN(key1, key2)  ((char*)(key1) < (char*)(key2))
  4 
  5 /* The randombits() function below is a fast-and-dirty generator that
  6  * is probably irregular enough for our purposes.  Note that it's biased:
  7  * I think that ones are slightly more probable than zeroes.  It's not
  8  * important here, though.
  9  */
 10 
 11 static unsigned int random_value = 1;
 12 static unsigned int random_stream = 0;
 13 
 14 static int
 15 randombits(int bits)
 16 {
 17     int result;
 18     if (random_stream < (1U << bits)) {
 19         random_value *= 1082527;
 20         random_stream = random_value;
 21     }
 22     result = random_stream & ((1<<bits)-1);
 23     random_stream >>= bits;
 24     return result;
 25 }
 26 
 27 
 28 /* Insert a new node into the tree.
 29    (*root) is modified to point to the new root. */
 30 void
 31 RotatingTree_Add(rotating_node_t **root, rotating_node_t *node)
 32 {
 33     while (*root != NULL) {
 34         if (KEY_LOWER_THAN(node->key, (*root)->key))
 35             root = &((*root)->left);
 36         else
 37             root = &((*root)->right);
 38     }
 39     node->left = NULL;
 40     node->right = NULL;
 41     *root = node;
 42 }
 43 
 44 /* Locate the node with the given key.  This is the most complicated
 45    function because it occasionally rebalances the tree to move the
 46    resulting node closer to the root. */
 47 rotating_node_t *
 48 RotatingTree_Get(rotating_node_t **root, void *key)
 49 {
 50     if (randombits(3) != 4) {
 51         /* Fast path, no rebalancing */
 52         rotating_node_t *node = *root;
 53         while (node != NULL) {
 54             if (node->key == key)
 55                 return node;
 56             if (KEY_LOWER_THAN(key, node->key))
 57                 node = node->left;
 58             else
 59                 node = node->right;
 60         }
 61         return NULL;
 62     }
 63     else {
 64         rotating_node_t **pnode = root;
 65         rotating_node_t *node = *pnode;
 66         rotating_node_t *next;
 67         int rotate;
 68         if (node == NULL)
 69             return NULL;
 70         while (1) {
 71             if (node->key == key)
 72                 return node;
 73             rotate = !randombits(1);
 74             if (KEY_LOWER_THAN(key, node->key)) {
 75                 next = node->left;
 76                 if (next == NULL)
 77                     return NULL;
 78                 if (rotate) {
 79                     node->left = next->right;
 80                     next->right = node;
 81                     *pnode = next;
 82                 }
 83                 else
 84                     pnode = &(node->left);
 85             }
 86             else {
 87                 next = node->right;
 88                 if (next == NULL)
 89                     return NULL;
 90                 if (rotate) {
 91                     node->right = next->left;
 92                     next->left = node;
 93                     *pnode = next;
 94                 }
 95                 else
 96                     pnode = &(node->right);
 97             }
 98             node = next;
 99         }
100     }
101 }
102 
103 /* Enumerate all nodes in the tree.  The callback enumfn() should return
104    zero to continue the enumeration, or non-zero to interrupt it.
105    A non-zero value is directly returned by RotatingTree_Enum(). */
106 int
107 RotatingTree_Enum(rotating_node_t *root, rotating_tree_enum_fn enumfn,
108                   void *arg)
109 {
110     int result;
111     rotating_node_t *node;
112     while (root != NULL) {
113         result = RotatingTree_Enum(root->left, enumfn, arg);
114         if (result != 0) return result;
115         node = root->right;
116         result = enumfn(root, arg);
117         if (result != 0) return result;
118         root = node;
119     }
120     return 0;
121 }