static AVLNode *avltree_node_remove(AVLNode *node, AVLKey key, vpointer *removed_data) { AVLNode *new_root=NULL; int old_balance; if (!node) return NULL; if (key < node->key) { if (node->left!=NULL) { old_balance = node->left->balance; node->left = avltree_node_remove(node->left, key, removed_data); node = avltree_node_restore_left_balance(node, old_balance); } } else if (key > node->key) { if (node->right!=NULL) { old_balance = node->right->balance; node->right = avltree_node_remove(node->right, key, removed_data); node = avltree_node_restore_right_balance(node, old_balance); } } else if (key == node->key) { AVLNode *removed_node; removed_node = node; if (!node->right) { node = node->left; } else { old_balance = node->right->balance; node->right = avltree_node_remove_leftmost(node->right, &new_root); if (new_root==NULL) die("Internal error. New root node is NULL."); new_root->left = node->left; new_root->right = node->right; new_root->balance = node->balance; node = avltree_node_restore_right_balance(new_root, old_balance); } *removed_data = removed_node->data; avltree_node_free(removed_node); } return node; }
GAULFUNC vpointer avltree_remove_key(AVLTree *tree, AVLKey key) { vpointer removed=NULL; if (!tree || !tree->root) return NULL; tree->root = avltree_node_remove(tree->root, key, &removed); return removed; }
GAULFUNC vpointer avltree_remove(AVLTree *tree, vpointer data) { vpointer removed=NULL; if (!tree || !tree->root) return NULL; tree->root = avltree_node_remove(tree->root, tree->key_generate_func(data), &removed); return removed; }
bool test_avltree() { unsigned int i, list[8] = { 4, 2, 3, 7, 1, 0, 6, 5 }, trim[5] = { 1, 2, 5, 6, 7 }; struct avltree_node_t *root = NULL, *cur, node[10000]; printf("testing avltree... "); { for(i = 0; i < 8; i++) avltree_node_insert(&root, &node[list[i]], (avltree_compare_nodenode_f)compare_ptr, NULL); for(i = 0, cur = avltree_node_first(root); i < 8; i++, cur = avltree_node_next(cur)) { if(cur != &node[i]) return printf("failed\n"), false; } avltree_node_remove(&root, &node[list[2]], (avltree_compare_nodekey_f)compare_ptr, NULL); avltree_node_remove(&root, &node[list[5]], (avltree_compare_nodekey_f)compare_ptr, NULL); avltree_node_remove(&root, &node[list[0]], (avltree_compare_nodekey_f)compare_ptr, NULL); for(i = 0, cur = avltree_node_first(root); i < 5; i++, cur = avltree_node_next(cur)) { if(cur != &node[trim[i]]) return printf("failed\n"), false; } } { root = NULL; for(i = 0; i < 1000; i++) avltree_node_insert(&root, &node[i*443%1000], (avltree_compare_nodenode_f)compare_ptr, NULL); for(i = 0, cur = avltree_node_first(root); i < 1000; i++, cur = avltree_node_next(cur)) { if(cur != &node[i]) return printf("failed\n"), false; else if((cur->balance < -1) || (cur->balance > 1)) return printf("failed\n"), false; } } { root = NULL; for(i = 0; i < 10000; i++) avltree_node_insert(&root, &node[i*5333%10000], (avltree_compare_nodenode_f)compare_ptr, NULL); for(i = 10000 - 1, cur = avltree_node_last(root); i != UINT_MAX; i--, cur = avltree_node_prev(cur)) { if(cur != &node[i]) return printf("failed\n"), false; else if((cur->balance < -1) || (cur->balance > 1)) return printf("failed\n"), false; } for(i = 1; i < 10000; i++) { if(avltree_node_atmost(root, (void *)&node[i] - 1, (avltree_compare_nodekey_f)compare_ptr, NULL) != &node[i - 1]) return printf("failed\n"), false; } for(i = 0; i < 10000 - 1; i++) { if(avltree_node_atleast(root, (void *)&node[i] + 1, (avltree_compare_nodekey_f)compare_ptr, NULL) != &node[i + 1]) return printf("failed\n"), false; } } printf("okay\n"); return true; }