Exemple #1
0
/******************************************************************************
 **函数名称: _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;
}
Exemple #2
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;
}