/* delete an node from tree */ static avl_node_t* avl_remove_node(avl_node_t* root, avl_key_t key) { int factor = 0; int rotate = 0; if (root == NULL) return NULL; if (key < root->key) { root->left = avl_remove_node(root->left, key); } else if (key > root->key) { root->right = avl_remove_node(root->right, key); } else /* this is the node to be deleted */ { if ((root->left == NULL) || (root->right == NULL)) { avl_node_t* node = (root->left ? root->left : root->right); if (node != NULL) /* one child case */ { *root = *node; } else /* no child case */ { node = root; root = NULL; } avl_free_node(node); } else /* node with two children */ { avl_node_t* node = avl_node_min(root->right); root->key = node->key; root->data = node->data; root->right = avl_remove_node(root->right, node->key); } } if (root == NULL) return NULL; root->height = MAX(HEIGHT(root->left), HEIGHT(root->right)) + 1; factor = avl_get_balance(root); if (factor > 1) { int left_balance = avl_get_balance(root->left); rotate = (left_balance >= 0 ? ROT_LEFT : ROT_RIGHT); } else if (factor < -1) { int right_balance = avl_get_balance(root->right); rotate = (right_balance <= 0 ? ROT_RIGHT : ROT_LEFT); } return avl_balance_node(root, factor, rotate); }
int32_t bs_avl_remove(bs_avl_t* avl, avl_data_t data) { avl->root = (void*)avl_remove_node(avl, (avl_node_t*)avl->root, data); bs_debug("height diff:%d\n", avl_get_balance((avl_node_t*)avl->root)); return 0; }
static avl_node_t* avl_rebalance(avl_node_t *root) { avl_node_t *node = root; int32_t height_diff = avl_get_balance(root); if(height_diff > 1) { //bs_debug("rebalance! hight diff:%d, %d\n", height_diff, root->data); if(avl_get_balance(node->left_child) > 0) { node = avl_rotate_ll(root); } else { node = avl_rotate_lr(root); } } else if(height_diff < -1) { //bs_debug("rebalance! hight diff:%d, %d\n", height_diff, root->data); if(avl_get_balance(node->right_child) < 0) { node = avl_rotate_rr(root); } else { node = avl_rotate_rl(root); } } else { //bs_debug("do not rebalance :%d \n", root->data); } return node; }
/* insert an node to tree */ static avl_node_t* avl_insert_node(avl_node_t* root, avl_key_t key, void* data) { int rotate = 0; if (root == NULL) { return avl_new_node(key, data); } if (key < root->key) { rotate = ROT_LEFT; root->left = avl_insert_node(root->left, key, data); } else if (key > root->key) { rotate = ROT_RIGHT; root->right = avl_insert_node(root->right, key, data); } else assert(!"duplicated key insertion not supported"); /* update height */ root->height = MAX(HEIGHT(root->left), HEIGHT(root->right)) + 1; return avl_balance_node(root, avl_get_balance(root), rotate); }
void tree_print(tree_node *tn) { avl_node *node = (avl_node*)tn; printf("%d :: %d -> %d", avl_get_height(node), avl_get_balance(node), *(int*)node->value); }