symbian-qemu-0.9.1-12/python-2.6.1/Modules/rotatingtree.c
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     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 }