B树的定义

假设B树的度为t(t>=2),则B树满足如下要求:(参考算法导论)

(1)  每个非根节点至少包含t-1个关键字,t个指向子节点的指针;至多包含2t-1个关键字,2t个指向子女的指针(叶子节点的子女为空)。

(2)  节点的所有key按非降序存放,假设节点的关键字分别为K[1], K[2] … K[n], 指向子女的指针分别为P[1], P[2]…P[n+1],其中n为节点关键字的个数。则有:

P[1] <= K[1] <= P[2] <= K[2] …..<= K[n] <= P[n+1]   // 这里P[n]也指其指向的关键字

(3)  若根节点非空,则根节点至少包含两个子女;

(4)  所有的叶子节点都在同一层。

 

B树的搜索,searchroot, target

从root出发,对每个节点,找到大于或等于target关键字中最小的K[i],如果K[i]与target相等,则查找成功;否则在P[i]中递归搜索target,直到到达叶子节点,如仍未找到则说明关键字不在B树中,查找失败。

B树的插入,insert(root, target)

B树的插入需要沿着搜索的路径从root一直到叶节点,根据B树的规则,每个节点的关键字个数在[t-1, 2t-1]之间,故当target要加入到某个叶子时,如果该叶子节点已经有2t-1个关键字,则再加入target就违反了B树的定义,这时就需要对该叶子节点进行分裂,将叶子以中间节点为界,分成两个包含t-1个关键字的子节点,同时把中间节点提升到该叶子的父节点中,如果这样使得父节点的关键字个数超过2t-1,则要继续向上分裂,直到根节点,根节点的分裂会使得树加高一层。

上面的过程需要回溯,那么能否从根下降到叶节点后不回溯就能完成节点的插入呢?答案是肯定的,核心思想就是未雨绸缪,在下降的过程中,一旦遇到已满的节点(关键字个数为2t-1),就就对该节点进行分裂,这样就保证在叶子节点需要分裂时,其父节点一定是非满的,从而不需要再向上回溯。

B树的删除,delete(root, target)

在删除B树节点时,为了避免回溯,当遇到需要合并的节点时就立即执行合并,B树的删除算法如下:从root向叶子节点按照search规律遍历:

(1)  如果target在叶节点x中,则直接从x中删除target,情况(2)和(3)会保证当再叶子节点找到target时,肯定能借节点或合并成功而不会引起父节点的关键字个数少于t-1。

(2)  如果target在分支节点x中:

(a)  如果x的左分支节点y至少包含t个关键字,则找出y的最右的关键字prev,并替换target,并在y中递归删除prev。

(b)  如果x的右分支节点z至少包含t个关键字,则找出z的最左的关键字next,并替换target,并在z中递归删除next。

(c)  否则,如果y和z都只有t-1个关键字,则将targe与z合并到y中,使得y有2t-1个关键字,再从y中递归删除target。

(3)  如果关键字不在分支节点x中,则必然在x的某个分支节点p[i]中,如果p[i]节点只有t-1个关键字。

(a)  如果p[i-1]拥有至少t个关键字,则将x的某个关键字降至p[i]中,将p[i-1]的最大节点上升至x中。

(b)  如果p[i+1]拥有至少t个关键字,则将x个某个关键字降至p[i]中,将p[i+1]的最小关键字上升至x个。

(c)  如果p[i-1]与p[i+1]都拥有t-1个关键字,则将p[i]与其中一个兄弟合并,将x的一个关键字降至合并的节点中,成为中间关键字。

btree.c

#include <stdio.h>
#include <stdlib.h>

/**
 * @brief the degree of btree
 * key per node: [M-1, 2M-1]
 * child per node: [M, 2M]
 */
#define M 2

typedef struct btree_node {
    *M-];
    *M];
    int num;
    bool is_leaf;
} btree_node;

/**
 * @brief allocate a new btree node
 * default: is_leaf == true
 *
 * @return pointer of new node
 */
btree_node *btree_node_new();

/**
 * @brief create a btree root
 *
 * @return pointer of btree root
 */
btree_node *btree_create();

/**
 * @brief split child if num of key in child exceed 2M-1
 *
 * @param parent: parent of child
 * @param pos: p[pos] points to child
 * @param child: the node to be splited
 *
 * @return
 */
int btree_split_child(btree_node *parent, int pos, btree_node *child);

/**
 * @brief insert a value into btree
 * the num of key in node less than 2M-1
 *
 * @param node: tree root
 * @param target: target to insert
 */
void btree_insert_nonfull(btree_node *node, int target);

/**
 * @brief insert a value into btree

 *
 * @param root: tree root
 * @param target: target to insert
 *
 * @return: new root of tree
 */
btree_node* btree_insert(btree_node *root, int target);

/**
 * @brief merge y, z and root->k[pos] to left
 * this appens while y and z both have M-1 keys
 *
 * @param root: parent node
 * @param pos: postion of y
 * @param y: left node to merge
 * @param z: right node to merge
 */
void btree_merge_child(btree_node *root, int pos, btree_node *y, btree_node *z);

/**
 * @brief delete a vlue from btree
 *
 * @param root: btree root
 * @param target: target to delete
 *
 * @return: new root of tree
 */
btree_node *btree_delete(btree_node *root, int target);

/**
 * @brief delete a vlue from btree
 * root has at least M keys
 *
 * @param root: btree root
 * @param target: target to delete
 *
 * @return
 */
void btree_delete_nonone(btree_node *root, int target);

/**
 * @brief find the rightmost value
 *
 * @param root: root of tree
 *
 * @return: the rightmost value
 */
int btree_search_predecessor(btree_node *root);

/**
 * @brief find the leftmost value
 *
 * @param root: root of tree
 *
 * @return: the leftmost value
 */
int btree_search_successor(btree_node *root);

/**
 * @brief shift a value from z to y
 *
 * @param root: btree root
 * @param pos: position of y
 * @param y: left node
 * @param z: right node
 */
void btree_shift_to_left_child(btree_node *root, int pos, btree_node *y, btree_node *z);

/**
 * @brief shift a value from z to y
 *
 * @param root: btree root
 * @param pos: position of y
 * @param y: left node
 * @param z: right node
 */
void btree_shift_to_right_child(btree_node *root, int pos, btree_node *y, btree_node *z);

/**
 * @brief inorder traverse the btree
 *
 * @param root: root of treee
 */
void btree_inorder_print(btree_node *root);

/**
 * @brief level print the btree
 *
 * @param root: root of tree
 */
void btree_level_display(btree_node *root);

btree_node *btree_node_new()
{
    btree_node *node = (btree_node *)malloc(sizeof(btree_node));
    if(NULL == node) {
        return NULL;
    }

    ; i <  * M -; i++) {
        node->k[i] = ;
    }

    ; i <  * M; i++) {
        node->p[i] = NULL;
    }

    node->num = ;
    node->is_leaf = true;
}

btree_node *btree_create()
{
    btree_node *node = btree_node_new();
    if(NULL == node) {
        return NULL;
    }

    return node;
}

int btree_split_child(btree_node *parent, int pos, btree_node *child)
{
    btree_node *new_child = btree_node_new();
    if(NULL == new_child) {
        ;
    }

    new_child->is_leaf = child->is_leaf;
    new_child->num = M - ;

    ; i < M - ; i++) {
        new_child->k[i] = child->k[i+M];
    }

    if(false == new_child->is_leaf) {
        ; i < M; i++) {
            new_child->p[i] = child->p[i+M];
        }
    }

    child->num = M - ;

    for(int i = parent->num; i > pos; i--) {
        parent->p[i+] = parent->p[i];
    }
    parent->p[pos+] = new_child;

    ; i >= pos; i--) {
        parent->k[i+] = parent->k[i];
    }
    parent->k[pos] = child->k[M-];

    parent->num += ;
}

void btree_insert_nonfull(btree_node *node, int target)
{
     == node->is_leaf) {
        int pos = node->num;
         && target < node->k[pos-]) {
            node->k[pos] = node->k[pos-];
            pos--;
        }

        node->k[pos] = target;
        node->num += ;

    } else {
        int pos = node->num;
         && target < node->k[pos-]) {
            pos--;
        }

         * M - == node->p[pos]->num) {
            btree_split_child(node, pos, node->p[pos]);
            if(target > node->k[pos]) {
                pos++;
            }
        }

        btree_insert_nonfull(node->p[pos], target);
    }
}

btree_node* btree_insert(btree_node *root, int target)
{
    if(NULL == root) {
        return NULL;
    }

     * M -  == root->num) {
        btree_node *node = btree_node_new();
        if(NULL == node) {
            return root;
        }

        node->is_leaf = ;
        node->p[] = root;
        btree_split_child(node, , root);
        btree_insert_nonfull(node, target);
        return node;
    } else {
        btree_insert_nonfull(root, target);
        return root;
    }
}

void btree_merge_child(btree_node *root, int pos, btree_node *y, btree_node *z)
{
    y->num =  * M - ;
     * M - ; i++) {
        y->k[i] = z->k[i-M];
    }
    y->k[M-] = root->k[pos];

    if(false == z->is_leaf) {
         * M; i++) {
            y->p[i] = z->p[i-M];
        }
    }

    ; j < root->num; j++) {
        root->k[j-] = root->k[j];
        root->p[j] = root->p[j+];
    }

    root->num -= ;
    free(z);
}

btree_node *btree_delete(btree_node *root, int target)
{
     == root->num) {
        btree_node *y = root->p[];
        btree_node *z = root->p[];
        if(NULL != y && NULL != z &&
                M -  == y->num && M -  == z->num) {
            btree_merge_child(root, , y, z);
            free(root);
            btree_delete_nonone(y, target);
            return y;
        } else {
            btree_delete_nonone(root, target);
            return root;
        }
    } else {
        btree_delete_nonone(root, target);
        return root;
    }
}

void btree_delete_nonone(btree_node *root, int target)
{
    if(true == root->is_leaf) {
        ;
        while(i < root->num && target > root->k[i]) i++;
        if(target == root->k[i]) {
            ; j <  * M - ; j++) {
                root->k[j-] = root->k[j];
            }
            root->num -= ;
        } else {
            printf("target not found\n");
        }
    } else {
        ;
        btree_node *y = NULL, *z = NULL;
        while(i < root->num && target > root->k[i]) i++;
        if(i < root->num && target == root->k[i]) {
            y = root->p[i];
            z = root->p[i+];
            ) {
                int pre = btree_search_predecessor(y);
                root->k[i] = pre;
                btree_delete_nonone(y, pre);
            } ) {
                int next = btree_search_successor(z);
                root->k[i] = next;
                btree_delete_nonone(z, next);
            } else {
                btree_merge_child(root, i, y, z);
                btree_delete(y, target);
            }
        } else {
            y = root->p[i];
            if(i < root->num) {
                z = root->p[i+];
            }
            btree_node *p = NULL;
            ) {
                p = root->p[i-];
            }

            ) {
                 && p->num > M - ) {
                    btree_shift_to_right_child(root, i-, p, y);
                } ) {
                    btree_shift_to_left_child(root, i, y, z);
                } ) {
                    btree_merge_child(root, i-, p, y); // note
                    y = p;
                } else {
                    btree_merge_child(root, i, y, z);
                }
                btree_delete_nonone(y, target);
            } else {
                btree_delete_nonone(y, target);
            }
        }

    }
}

int btree_search_predecessor(btree_node *root)
{
    btree_node *y = root;
    while(false == y->is_leaf) {
        y = y->p[y->num];
    }
    ];
}

int btree_search_successor(btree_node *root)
{
    btree_node *z = root;
    while(false == z->is_leaf) {
        z = z->p[];
    }
    ];
}

void btree_shift_to_right_child(btree_node *root, int pos,
        btree_node *y, btree_node *z)
{
    z->num += ;
    ; i > ; i--) {
        z->k[i] = z->k[i-];
    }
    z->k[]= root->k[pos];
    root->k[pos] = y->k[y->num-];

    if(false == z->is_leaf) {
        ; i--) {
            z->p[i] = z->p[i-];
        }
        z->p[] = y->p[y->num];
    }

    y->num -= ;
}

void btree_shift_to_left_child(btree_node *root, int pos,
        btree_node *y, btree_node *z)
{
    y->num += ;
    y->k[y->num-] = root->k[pos];
    root->k[pos] = z->k[];

    ; j < z->num; j++) {
        z->k[j-] = z->k[j];
    }

    if(false == z->is_leaf) {
        y->p[y->num] = z->p[];
        ; j <= z->num; j++) {
            z->p[j-] = z->p[j];
        }
    } 

    z->num -= ;
}

void btree_inorder_print(btree_node *root)
{
    if(NULL != root) {
        btree_inorder_print(root->p[]);
        ; i < root->num; i++) {
            printf("%d ", root->k[i]);
            btree_inorder_print(root->p[i+]);
        }
    }
}

void btree_level_display(btree_node *root)
{
    // just for simplicty, can't exceed 200 nodes in the tree
    btree_node *queue[] = {NULL};
    ;
    ;

    queue[rear++] = root;

    while(front < rear) {
        btree_node *node = queue[front++];

        printf("[");
        ; i < node->num; i++) {
            printf("%d ", node->k[i]);
        }
        printf("]");

        ; i <= node->num; i++) {
            if(NULL != node->p[i]) {
                queue[rear++] = node->p[i];
            }
        }
    }
    printf("\n");
}

int main()
{
    , , , , , , , , , , , , };

    btree_node *root = btree_create();

    ; i < sizeof(arr) / sizeof(int); i++) {
        root = btree_insert(root, arr[i]);
        btree_level_display(root);
    }

    //int todel[] = {15, 18, 23, 30, 31, 52, 50};
    };
    ; i < sizeof(todel) / sizeof(int); i++) {
        printf("after delete %d\n", todel[i]);
        root = btree_delete(root, todel[i]);
        btree_level_display(root);
    } 

    ;
}

B+

与B树不同的时,B+树的关键字都存储在叶子节点,分支节点均为索引,在实现上大致与B树类似,在几个细节稍有不同。

(1) 数据结构中增加prev,next指针,用于将叶子节点串成有序双向链表。

(2) 在节点分裂的时候,如果分裂的节点为叶子,则需要把中间节点保留在左(或右)边的分支上,并且需要更新prev和next。

(3) 在节点合的时候,如果合并的节点为叶子,不需要把跟节点下降为中间节点,并且需要更新prev和next。

(4) 在向邻接节点借节点时,借来的关键字并不是父节点的关键字,而是邻接点的关键字,并根据实际情况更新父节点的索引。

bplustree.c

#include <stdio.h>
#include <stdlib.h>

/**
 * @brief the degree of btree
 * key per node: [M-1, 2M-1]
 * child per node: [M, 2M]
 */
#define M 2  // the degree of btree

typedef struct btree_node {
    *M-];
    *M];
    int num;
    bool is_leaf;
    struct btree_node *prev;  // use one struct just for simple
    struct btree_node *next;
} btree_node;

/**
 * @brief allocate a new btree node
 * default: is_leaf == true
 *
 * @return pointer of new node
 */
btree_node *btree_node_new();

/**
 * @brief create a btree root
 *
 * @return pointer of btree root
 */
btree_node *btree_create();

/**
 * @brief split child if num of key in child exceed 2M-1
 *
 * @param parent: parent of child
 * @param pos: p[pos] points to child
 * @param child: the node to be splited
 *
 * @return
 */
int btree_split_child(btree_node *parent, int pos, btree_node *child);

/**
 * @brief insert a value into btree
 * the num of key in node less than 2M-1
 *
 * @param node: tree root
 * @param target: target to insert
 */
void btree_insert_nonfull(btree_node *node, int target);

/**
 * @brief insert a value into btree

 *
 * @param root: tree root
 * @param target: target to insert
 *
 * @return: new root of tree
 */
btree_node* btree_insert(btree_node *root, int target);

/**
 * @brief merge y, z and root->k[pos] to left
 * this appens while y and z both have M-1 keys
 *
 * @param root: parent node
 * @param pos: postion of y
 * @param y: left node to merge
 * @param z: right node to merge
 */
void btree_merge_child(btree_node *root, int pos, btree_node *y, btree_node *z);

/**
 * @brief delete a vlue from btree
 *
 * @param root: btree root
 * @param target: target to delete
 *
 * @return: new root of tree
 */
btree_node *btree_delete(btree_node *root, int target);

/**
 * @brief delete a vlue from btree
 * root has at least M keys
 *
 * @param root: btree root
 * @param target: target to delete
 *
 * @return
 */
void btree_delete_nonone(btree_node *root, int target);

/**
 * @brief find the rightmost value
 *
 * @param root: root of tree
 *
 * @return: the rightmost value
 */
int btree_search_predecessor(btree_node *root);

/**
 * @brief find the leftmost value
 *
 * @param root: root of tree
 *
 * @return: the leftmost value
 */
int btree_search_successor(btree_node *root);

/**
 * @brief shift a value from z to y
 *
 * @param root: btree root
 * @param pos: position of y
 * @param y: left node
 * @param z: right node
 */
void btree_shift_to_left_child(btree_node *root, int pos, btree_node *y, btree_node *z);

/**
 * @brief shift a value from z to y
 *
 * @param root: btree root
 * @param pos: position of y
 * @param y: left node
 * @param z: right node
 */
void btree_shift_to_right_child(btree_node *root, int pos, btree_node *y, btree_node *z);

/**
 * @brief inorder traverse the btree
 *
 * @param root: root of treee
 */
void btree_inorder_print(btree_node *root);

/**
 * @brief print tree linearly using prev/next pointer
 *
 * @param root: root of tree
 */
void btree_linear_print(btree_node *root);

/**
 * @brief level print the btree
 *
 * @param root: root of tree
 */
void btree_level_display(btree_node *root);

btree_node *btree_node_new()
{
    btree_node *node = (btree_node *)malloc(sizeof(btree_node));
    if(NULL == node) {
        return NULL;
    }

    ; i <  * M -; i++) {
        node->k[i] = ;
    }

    ; i <  * M; i++) {
        node->p[i] = NULL;
    }

    node->num = ;
    node->is_leaf = true;
    node->prev = NULL;
    node->next = NULL;
}

btree_node *btree_create()
{
    btree_node *node = btree_node_new();
    if(NULL == node) {
        return NULL;
    }

    node->next = node;
    node->prev = node;

    return node;
}

int btree_split_child(btree_node *parent, int pos, btree_node *child)
{
    btree_node *new_child = btree_node_new();
    if(NULL == new_child) {
        ;
    }

    new_child->is_leaf = child->is_leaf;
    new_child->num = M - ;

    ; i < M - ; i++) {
        new_child->k[i] = child->k[i+M];
    }

    if(false == new_child->is_leaf) {
        ; i < M; i++) {
            new_child->p[i] = child->p[i+M];
        }
    }

    child->num = M - ;
    if(true == child->is_leaf) {
        child->num++;  // if leaf, keep the middle ele, put it in the left
    }

    for(int i = parent->num; i > pos; i--) {
        parent->p[i+] = parent->p[i];
    }
    parent->p[pos+] = new_child;

    ; i >= pos; i--) {
        parent->k[i+] = parent->k[i];
    }
    parent->k[pos] = child->k[M-];

    parent->num += ;

    // update link
    if(true == child->is_leaf) {
        new_child->next = child->next;
        child->next->prev = new_child;
        new_child->prev = child;
        child->next = new_child;
    }
}

void btree_insert_nonfull(btree_node *node, int target)
{
     == node->is_leaf) {
        int pos = node->num;
         && target < node->k[pos-]) {
            node->k[pos] = node->k[pos-];
            pos--;
        }

        node->k[pos] = target;
        node->num += ;

    } else {
        int pos = node->num;
         && target < node->k[pos-]) {
            pos--;
        }

         * M - == node->p[pos]->num) {
            btree_split_child(node, pos, node->p[pos]);
            if(target > node->k[pos]) {
                pos++;
            }
        }

        btree_insert_nonfull(node->p[pos], target);
    }
}

btree_node* btree_insert(btree_node *root, int target)
{
    if(NULL == root) {
        return NULL;
    }

     * M -  == root->num) {
        btree_node *node = btree_node_new();
        if(NULL == node) {
            return root;
        }

        node->is_leaf = ;
        node->p[] = root;
        btree_split_child(node, , root);
        btree_insert_nonfull(node, target);
        return node;
    } else {
        btree_insert_nonfull(root, target);
        return root;
    }
}

void btree_merge_child(btree_node *root, int pos, btree_node *y, btree_node *z)
{
    if(true == y->is_leaf) {
        y->num =  * M - ;
         * M - ; i++) {
            y->k[i-] = z->k[i-M];
        }
    } else {
        y->num =  * M - ;
         * M - ; i++) {
            y->k[i] = z->k[i-M];
        }
        y->k[M-] = root->k[pos];
         * M; i++) {
            y->p[i] = z->p[i-M];
        }
    }

    ; j < root->num; j++) {
        root->k[j-] = root->k[j];
        root->p[j] = root->p[j+];
    }

    root->num -= ;

    // update link
    if(true == y->is_leaf) {
        y->next = z->next;
        z->next->prev = y;
    }

    free(z);
}

btree_node *btree_delete(btree_node *root, int target)
{
     == root->num) {
        btree_node *y = root->p[];
        btree_node *z = root->p[];
        if(NULL != y && NULL != z &&
                M -  == y->num && M -  == z->num) {
            btree_merge_child(root, , y, z);
            free(root);
            btree_delete_nonone(y, target);
            return y;
        } else {
            btree_delete_nonone(root, target);
            return root;
        }
    } else {
        btree_delete_nonone(root, target);
        return root;
    }
}

void btree_delete_nonone(btree_node *root, int target)
{
    if(true == root->is_leaf) {
        ;
        while(i < root->num && target > root->k[i]) i++;
        if(target == root->k[i]) {
            ; j <  * M - ; j++) {
                root->k[j-] = root->k[j];
            }
            root->num -= ;
        } else {
            printf("target not found\n");
        }
    } else {
        ;
        btree_node *y = NULL, *z = NULL;
        while(i < root->num && target > root->k[i]) i++;

        y = root->p[i];
        if(i < root->num) {
            z = root->p[i+];
        }
        btree_node *p = NULL;
        ) {
            p = root->p[i-];
        }

        ) {
             && p->num > M - ) {
                btree_shift_to_right_child(root, i-, p, y);
            } ) {
                btree_shift_to_left_child(root, i, y, z);
            } ) {
                btree_merge_child(root, i-, p, y);
                y = p;
            } else {
                btree_merge_child(root, i, y, z);
            }
            btree_delete_nonone(y, target);
        } else {
            btree_delete_nonone(y, target);
        }
    }
}

int btree_search_predecessor(btree_node *root)
{
    btree_node *y = root;
    while(false == y->is_leaf) {
        y = y->p[y->num];
    }
    ];
}

int btree_search_successor(btree_node *root)
{
    btree_node *z = root;
    while(false == z->is_leaf) {
        z = z->p[];
    }
    ];
}

void btree_shift_to_right_child(btree_node *root, int pos,
        btree_node *y, btree_node *z)
{
    z->num += ;

    if(false == z->is_leaf) {
        z->k[] = root->k[pos];
        root->k[pos] = y->k[y->num-];
    } else {
        z->k[] = y->k[y->num-];
        root->k[pos] = y->k[y->num-];
    }

    ; i > ; i--) {
        z->k[i] = z->k[i-];
    }

    if(false == z->is_leaf) {
        ; i--) {
            z->p[i] = z->p[i-];
        }
        z->p[] = y->p[y->num];
    } 

    y->num -= ;
}

void btree_shift_to_left_child(btree_node *root, int pos,
        btree_node *y, btree_node *z)
{
    y->num += ;

    if(false == z->is_leaf) {
        y->k[y->num-] = root->k[pos];
        root->k[pos] = z->k[];
    } else {
        y->k[y->num-] = z->k[];
        root->k[pos] = z->k[];
    }

    ; j < z->num; j++) {
        z->k[j-] = z->k[j];
    }

    if(false == z->is_leaf) {
        y->p[y->num] = z->p[];
        ; j <= z->num; j++) {
            z->p[j-] = z->p[j];
        }
    } 

    z->num -= ;
}

void btree_inorder_print(btree_node *root)
{
    if(NULL != root) {
        btree_inorder_print(root->p[]);
        ; i < root->num; i++) {
            printf("%d ", root->k[i]);
            btree_inorder_print(root->p[i+]);
        }
    }
}

void btree_linear_print(btree_node *root)
{
    if(NULL != root) {
        btree_node *leftmost = root;
        while(false == leftmost->is_leaf) {
            leftmost = leftmost->p[];
        }

        btree_node *iter = leftmost;
        do {
            ; i < iter->num; i++) {
                printf("%d ", iter->k[i]);
            }
            iter = iter->next;
        } while(iter != leftmost);
        printf("\n");
    }
}

void btree_level_display(btree_node *root)
{

    // just for simplicty, can't exceed 200 nodes in the tree
    btree_node *queue[] = {NULL};
    ;
    ;

    queue[rear++] = root;

    while(front < rear) {
        btree_node *node = queue[front++];

        printf("[");
        ; i < node->num; i++) {
            printf("%d ", node->k[i]);
        }
        printf("]");

        ; i <= node->num; i++) {
            if(NULL != node->p[i]) {
                queue[rear++] = node->p[i];
            }
        }
    }
    printf("\n");
}

int main()
{
    , , , , , , , , , , , , };
//    int arr[] = {18, 31, 12, 10};

    btree_node *root = btree_create();

    ; i < sizeof(arr) / sizeof(int); i++) {
        root = btree_insert(root, arr[i]);
        btree_level_display(root);
        btree_linear_print(root);
    }

    //int todel[] = {15, 18, 23, 30, 31, 52, 50};
    , , , };
    ; i < sizeof(todel) / sizeof(int); i++) {
        printf("after delete %d\n", todel[i]);
        root = btree_delete(root, todel[i]);
        btree_level_display(root);
        btree_linear_print(root);
    } 

    ;
}

B树算法与实现 (C语言实现)的更多相关文章

  1. R语言 决策树算法

    定义: 决策树(Decision Tree)是在已知各种情况发生概率的基础上,通过构成决策树来求取净现值的期望值大于等于零的概率,评价项目风险,判断其可行性的决策分析方法,是直观运用概率分析的一种图解 ...

  2. 机器学习-决策树算法+代码实现(基于R语言)

    分类树(决策树)是一种十分常用的分类方法.核心任务是把数据分类到可能的对应类别. 他是一种监管学习,所谓监管学习就是给定一堆样本,每个样本都有一组属性和一个类别,这些类别是事先确定的,通过学习得到一个 ...

  3. [转]机器学习——C4.5 决策树算法学习

    1. 算法背景介绍 分类树(决策树)是一种十分常用的分类方法.它是一种监管学习,所谓监管学习说白了很简单,就是给定一堆样本,每个样本都有一组属性和一个类别,这些类别是事先确定的,那么通过学习得到一个分 ...

  4. 零基础数据分析与挖掘R语言实战课程(R语言)

    随着大数据在各行业的落地生根和蓬勃发展,能从数据中挖金子的数据分析人员越来越宝贝,于是很多的程序员都想转行到数据分析, 挖掘技术哪家强?当然是R语言了,R语言的火热程度,从TIOBE上编程语言排名情况 ...

  5. 大数据时代的精准数据挖掘——使用R语言

    老师简介: Gino老师,即将步入不惑之年,早年获得名校数学与应用数学专业学士和统计学专业硕士,有海外学习和工作的经历,近二十年来一直进行着数据分析的理论和实践,数学.统计和计算机功底强悍. 曾在某一 ...

  6. Linux内核源码分析--内核启动之(3)Image内核启动(C语言部分)(Linux-3.0 ARMv7)

    http://blog.chinaunix.net/uid-20543672-id-3157283.html Linux内核源码分析--内核启动之(3)Image内核启动(C语言部分)(Linux-3 ...

  7. R语言进行机器学习方法及实例(一)

    版权声明:本文为博主原创文章,转载请注明出处   机器学习的研究领域是发明计算机算法,把数据转变为智能行为.机器学习和数据挖掘的区别可能是机器学习侧重于执行一个已知的任务,而数据发掘是在大数据中寻找有 ...

  8. R语言︱XGBoost极端梯度上升以及forecastxgb(预测)+xgboost(回归)双案例解读

    XGBoost不仅仅可以用来做分类还可以做时间序列方面的预测,而且已经有人做的很好,可以见最后的案例. 应用一:XGBoost用来做预测 ------------------------------- ...

  9. R语言︱决策树族——随机森林算法

    每每以为攀得众山小,可.每每又切实来到起点,大牛们,缓缓脚步来俺笔记葩分享一下吧,please~ --------------------------- 笔者寄语:有一篇<有监督学习选择深度学习 ...

随机推荐

  1. ASP.NET 页生命周期概述

    ASP.NET 页生命周期概述 Visual Studio 2005    ASP.NET 页运行时,此页将经历一个生命周期,在生命周期中将执行一系列处理步骤.这些步骤包括初始化.实例化控件.还原和维 ...

  2. Griddle, griddle-react 一个REACT 表格组件

    Griddle, griddle-react 一个REACT 表格组件: http://griddlegriddle.github.io/Griddle/index.html

  3. trap

    http://blog.csdn.net/elbort/article/details/8525599 http://mywiki.wooledge.org/SignalTrap

  4. struts2 action 3中书写方式

    1.pojo类   简单的javabean 类 需要有 public String execute(){return null;} 2.实现 Action 借口  重写 execute 3.继承 Ac ...

  5. Shell 语法 if 、 case 、for 、 while、 until 、select 、repeat、子函数

    if语法 :   if [ expression ]    then   commandselif [ expression2 ]   then   commandselse   commandsfi ...

  6. ios oc 和 swfit 用dispatch_once 创建单例

    网上已经有方法了,我这里就是抄了下,原文链接 http://bj007.blog.51cto.com/1701577/649413 http://blog.csdn.net/u010124617/ar ...

  7. java web 学习 --第四天(Java三级考试)

    第三天的学习内容:http://www.cnblogs.com/tobecrazy/p/3453041.html jsp内置对象 out out 属性类型:JspWriter 作用域:page 作用: ...

  8. 16~25.spring+hibernate简单实例 .连接数据库并进行增删改查

    1.概念 Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,它将POJO与数据库表建立映射关系,是一个全自动的orm框架,hibernate可以自动生成SQ ...

  9. ABAP 行列稳定刷新语句

    DATA stbl TYPE lvc_s_stbl. stbl-row = 'X'." 基于行的稳定刷新         stbl-col = 'X'." 基于列稳定刷新      ...

  10. [Android]检查当前手机是否有网络

    // Check network connection private boolean isNetworkConnected(){ ConnectivityManager connectivityMa ...