/****************************************************************************** **函数名称: _btree_merge **功 能: 合并结点 **输入参数: ** btree: B树 ** node: ** brother: **输出参数: NONE **返 回: 0:成功 !0:失败 **实现描述: **注意事项: **作 者: # Qifeng.zou # 2014.03.12 # ******************************************************************************/ static int _btree_merge(btree_t *btree, btree_node_t *left, btree_node_t *right, int mid) { int m; btree_node_t *parent = left->parent; left->key[left->num] = parent->key[mid]; left->data[left->num] = parent->data[mid]; ++left->num; memcpy(left->key + left->num, right->key, right->num*sizeof(int)); memcpy(left->data + left->num, right->data, right->num*sizeof(void *)); memcpy(left->child + left->num, right->child, (right->num+1)*sizeof(btree_node_t *)); for (m=0; m<=right->num; m++) { if (NULL != right->child[m]) { right->child[m]->parent = left; } } left->num += right->num; for (m=mid; m<parent->num-1; m++) { parent->key[m] = parent->key[m+1]; parent->data[m] = parent->data[m+1]; parent->child[m+1] = parent->child[m+2]; } parent->key[m] = 0; parent->data[m] = NULL; parent->child[m+1] = NULL; parent->num--; btree->dealloc(btree->pool, right->child); btree->dealloc(btree->pool, right->key); btree->dealloc(btree->pool, right->data); btree->dealloc(btree->pool, right); /* Check */ if (parent->num < btree->min) { return btree_merge(btree, parent); } return 0; }
/****************************************************************************** **函数名称: _btree_remove **功 能: 在指定结点删除指定关键字 **输入参数: ** btree: B树 ** node: 指定结点 ** idx: 将被删除的关键字在结点node中位置(0 ~ node->num - 1) **输出参数: NONE **返 回: 0:成功 !0:失败 **实现描述: ** 使用node->child[idx]中的最大值替代被删除的关键字, ** 并依次向下处理直至最底层结点, ** -- 其实最终其处理过程相当于是删除最底层结点的关键字 **注意事项: **作 者: # Qifeng.zou # 2014.03.12 # ******************************************************************************/ static int _btree_remove(btree_t *btree, btree_node_t *node, int idx) { btree_node_t *orig = node, *child = node->child[idx]; /* 使用node->child[idx]中的最大值替代被删除的关键字 */ while (NULL != child) { node = child; child = node->child[child->num]; } orig->key[idx] = node->key[node->num - 1]; orig->data[idx] = node->data[node->num - 1]; /* 最终其处理过程相当于是删除最底层结点的关键字 */ --node->num; node->key[node->num] = 0; node->data[node->num] = NULL; if (node->num < btree->min) { return btree_merge(btree, node); } return 0; }
/** * btree_delete_internal * @access private * @param btree struct * @param btree node * @param key that was requested for deletion * @param current key * @param data index * @return int 1 on success, 0 on failure * * Removes a node at key from the btree * Locks the entire tree until complete */ static int btree_delete_internal(btree_tree *t, btree_node *node, uint64_t key_to_delete, uint64_t key, uint32_t *data_idx_to_free) { uint32_t idx; uint32_t data_idx; /* if x is a leaf then * if k is in x then * delete k from x and return true * else return false //k is not in subtree */ if (node->leaf) { if (btree_check_key_in_node(node, key, &idx, &data_idx)) { btree_delete_key_idx_from_node(node, idx); btree_delete_branch_idx_from_node(node, idx); if (key == key_to_delete) { *data_idx_to_free = data_idx; } return 1; } else { return 0; } } else { /* if k is in x then */ if (btree_check_key_in_node(node, key, &idx, &data_idx)) { btree_node *y, *node_with_prev_key; /* Record the data_idx for this key */ if (key == key_to_delete) { *data_idx_to_free = data_idx; } /* y = the child of x that precedes k * if y has at least t keys then * k' = the predecessor of k (use B-Tree-FindLargest) * Copy k' over k //i.e., replace k with k' * B-Tree-Delete(y, k') //Note: recursive call */ y = btree_get_node(t, node->branch[idx]); if (y->nr_of_keys >= BTREE_T(t)) { node_with_prev_key = btree_find_greatest(t, y); node->keys[idx] = node_with_prev_key->keys[y->nr_of_keys-1]; return btree_delete_internal(t, y, key_to_delete, node_with_prev_key->keys[y->nr_of_keys-1].key, data_idx_to_free); } else { btree_node *z, *node_with_next_key; /* else //y has t-1 keys * z = the child of x that follows k * if z has at least t keys then * k' = the successor of k * Copy k' over k //i.e., replace k with k' * B-Tree-Delete(z, k') //Note: recursive call */ z = btree_get_node(t, node->branch[idx + 1]); if (z->nr_of_keys >= BTREE_T(t)) { node_with_next_key = btree_find_smallest(t, z); node->keys[idx] = node_with_next_key->keys[0]; btree_delete_internal(t, z, key_to_delete, node_with_next_key->keys[0].key, data_idx_to_free); } else { /* else //both y and z have t-1 keys * merge k and all of z into y //y now contains 2t-1 keys. * //k and the pointer to z will be deleted from x. * B-Tree-Delete(y, k) //Note: recursive call */ btree_merge(t, y, node, idx, z); btree_delete_key_idx_from_node(node, idx); btree_delete_branch_idx_from_node(node, idx + 1); btree_delete_internal(t, y, key_to_delete, key, data_idx_to_free); if (t->root->nr_of_keys == 0 && !t->root->leaf) { t->root = btree_get_node(t, t->root->branch[0]); } } } } else { btree_node *c; uint32_t i; c = btree_find_branch(t, node, key, &i); if (c->nr_of_keys <= BTREE_T(t) - 1) { btree_node *z, *node_with_prev_key, *node_with_next_key; btree_key tmp_key; /* Is there a left sibling with T or more keys? */ if (i > 0) { /* otherwise there is no left sibling */ z = btree_get_node(t, node->branch[i - 1]); if (z->nr_of_keys > BTREE_T(t) - 1) { node_with_prev_key = btree_find_greatest(t, z); btree_node_insert_key(t, c, 0, node_with_prev_key->keys[z->nr_of_keys-1]); btree_delete_internal(t, z, key_to_delete, node_with_prev_key->keys[z->nr_of_keys-1].key, data_idx_to_free); /* Swap parent and first key in C */ tmp_key = node->keys[i-1]; node->keys[i-1] = c->keys[0]; c->keys[0] = tmp_key; goto proceed; } } /* Is there a left sibling with T or more keys? */ if (i < node->nr_of_keys) { /* otherwise there is no right sibling */ z = btree_get_node(t, node->branch[i + 1]); if (z->nr_of_keys > BTREE_T(t) - 1) { node_with_next_key = btree_find_smallest(t, z); btree_node_insert_key(t, c, c->nr_of_keys, node_with_next_key->keys[0]); btree_delete_internal(t, z, key_to_delete, node_with_next_key->keys[0].key, data_idx_to_free); /* Swap parent and last key in C */ tmp_key = node->keys[i]; node->keys[i] = c->keys[c->nr_of_keys - 1]; c->keys[c->nr_of_keys - 1] = tmp_key; goto proceed; } } /* No siblings, so we need to merge. */ /* Is there a left sibling? */ if (i > 0) { /* otherwise there is no left sibling */ z = btree_get_node(t, node->branch[i - 1]); btree_merge(t, z, node, i - 1, c); btree_delete_branch_idx_from_node(node, i); btree_delete_key_idx_from_node(node, i - 1); if (t->root->nr_of_keys == 0 && !t->root->leaf) { t->root = btree_get_node(t, t->root->branch[0]); } return btree_delete_internal(t, z, key_to_delete, key, data_idx_to_free); } /* Is there a right sibling? */ if (i < node->nr_of_keys) { /* otherwise there is no right sibling */ z = btree_get_node(t, node->branch[i + 1]); btree_merge(t, c, node, i, z); btree_delete_branch_idx_from_node(node, i + 1); btree_delete_key_idx_from_node(node, i); if (t->root->nr_of_keys == 0 && !t->root->leaf) { t->root = btree_get_node(t, t->root->branch[0]); } return btree_delete_internal(t, c, key_to_delete, key, data_idx_to_free); } } proceed: return btree_delete_internal(t, c, key_to_delete, key, data_idx_to_free); } } return 0; }