数据结构 b+树

头文件

cpp 复制代码
#pragma once
#include <stdio.h>
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
using namespace std;

#define M 4  // B+树的阶数

// B+树节点结构
typedef struct BPlusTreeNode {
    int key_num;                     // 当前关键字数量
    int keys[M];                     // 关键字数组
    bool is_leaf;                    // 是否为叶子节点
    struct BPlusTreeNode* parent;    // 父节点指针
    struct BPlusTreeNode* children[M + 1];  // 子节点指针数组
    struct BPlusTreeNode* next;      // 叶子节点的下一个兄弟(链表连接)
    void** data_ptrs[M];             // 叶子节点的数据指针数组
} BPlusTreeNode;

// B+树结构
typedef struct BPlusTree {
    BPlusTreeNode* root;             // 根节点
    BPlusTreeNode* first_leaf;       // 第一个叶子节点(用于范围查询)
    int size;                        // 树中关键字总数
} BPlusTree;

// 查找结果结构
typedef struct SearchResult {
    BPlusTreeNode* node;             // 找到的节点
    int index;                       // 关键字位置
    bool found;                      // 是否找到
} SearchResult;

// 工具函数声明
// 创建查找结果
SearchResult* CreateSearchResult();
//创建节点
BPlusTreeNode* CreateNode(bool is_leaf);
//查找关键字位置
int FindKeyIndex(BPlusTreeNode* node, int key);


// 主要操作函数声明
//初始化B+树
void InitBPlusTree(BPlusTree* tree);
//查找
SearchResult* Search(BPlusTree* tree, int key);
//插入
bool Insert(BPlusTree* tree, int key, void* data);
// 删除
bool Delete(BPlusTree* tree, int key);
//显示
void Display(BPlusTree* tree, bool show_details = false);
//范围查询
void RangeQuery(BPlusTree* tree, int start_key, int end_key);
//销毁树
void DestroyTree(BPlusTree* tree);

源文件

cpp 复制代码
#include "b+树.h"

// 创建查找结果
SearchResult* CreateSearchResult() {
    SearchResult* result = (SearchResult*)malloc(sizeof(SearchResult));
    if (!result) {
        perror("Failed to allocate search result");
        exit(EXIT_FAILURE);
    }
    result->node = nullptr;
    result->index = -1;
    result->found = false;
    return result;
}
//创建节点
BPlusTreeNode* CreateNode(bool is_leaf) {
    BPlusTreeNode* node = (BPlusTreeNode*)malloc(sizeof(BPlusTreeNode));
    if (!node) {
        perror("Failed to allocate node");
        exit(EXIT_FAILURE);
    }
    node->key_num = 0;
    node->is_leaf = is_leaf;
    node->parent = nullptr;
    node->next = nullptr;
    memset(node->keys, 0, sizeof(node->keys));
    // 初始化指针数组
    for (int i = 0; i <= M; i++) {
        node->children[i] = nullptr;
        if (is_leaf && i < M) {
            node->data_ptrs[i] = nullptr;
        }
    }
    return node;
}
//查找关键字位置
int FindKeyIndex(BPlusTreeNode* node, int key) {
    int left = 0;
    int right = node->key_num - 1;
    while (left <= right) {
        int mid = left + (right - left) / 2;
        if (node->keys[mid] == key) {
            return mid;
        }
        else if (node->keys[mid] < key) {
            left = mid + 1;
        }
        else {
            right = mid - 1;
        }
    }
    return left; // 返回应该插入的位置
}

// ==================== 主要操作实现 ====================
//初始化B+树
void InitBPlusTree(BPlusTree* tree) {
    assert(tree != nullptr);
    tree->root = nullptr;
    tree->first_leaf = nullptr;
    tree->size = 0;
}
//查找
SearchResult* Search(BPlusTree* tree, int key) {
    assert(tree != nullptr);
    SearchResult* result = CreateSearchResult();
    if (tree->root == nullptr) {
        return result;
    }
    BPlusTreeNode* current = tree->root;
    // 查找合适的叶子节点
    while (!current->is_leaf) {
        int pos = FindKeyIndex(current, key);
        current = current->children[pos];
    }
    // 在叶子节点中查找关键字
    int pos = FindKeyIndex(current, key);
    result->node = current;
    result->index = pos;
    if (pos < current->key_num && current->keys[pos] == key) {
        result->found = true;
    }
    return result;
}
//插入
bool Insert(BPlusTree* tree, int key, void* data) {
    assert(tree != nullptr);
    // 空树情况
    if (tree->root == nullptr) {
        BPlusTreeNode* new_node = CreateNode(true);
        new_node->keys[0] = key;
        new_node->data_ptrs[0] = data;
        new_node->key_num = 1;
        tree->root = new_node;
        tree->first_leaf = new_node;
        tree->size = 1;
        return true;
    }
    // 查找插入位置
    SearchResult* result = Search(tree, key);
    if (result->found) {
        // 关键字已存在,更新数据
        result->node->data_ptrs[result->index] = data;
        free(result);
        return true;
    }
    BPlusTreeNode* leaf = result->node;
    int pos = result->index;
    free(result);
    // 在叶子节点中插入
    for (int i = leaf->key_num; i > pos; i--) {
        leaf->keys[i] = leaf->keys[i - 1];
        leaf->data_ptrs[i] = leaf->data_ptrs[i - 1];
    }
    leaf->keys[pos] = key;
    leaf->data_ptrs[pos] = data;
    leaf->key_num++;
    tree->size++;
    // 检查是否需要分裂
    if (leaf->key_num == M) {
        InsertAdjust(tree, leaf);
    }
    return true;
}
// 内部函数:分裂节点
BPlusTreeNode* SplitNode(BPlusTree* tree, BPlusTreeNode* node) {
    int split_pos = M / 2;
    bool is_leaf = node->is_leaf;
    // 创建新节点
    BPlusTreeNode* new_node = CreateNode(is_leaf);
    new_node->parent = node->parent;
    if (is_leaf) {
        // 叶子节点分裂
        for (int i = split_pos; i < M; i++) {
            int j = i - split_pos;
            new_node->keys[j] = node->keys[i];
            new_node->data_ptrs[j] = node->data_ptrs[i];
            new_node->key_num++;
            // 清空原节点
            node->keys[i] = 0;
            node->data_ptrs[i] = nullptr;
        }
        node->key_num = split_pos;
        // 维护叶子链表
        new_node->next = node->next;
        node->next = new_node;
    }
    else {
        // 内部节点分裂
        for (int i = split_pos + 1; i < M; i++) {
            int j = i - (split_pos + 1);
            new_node->keys[j] = node->keys[i];
            new_node->children[j] = node->children[i];
            if (node->children[i]) {
                node->children[i]->parent = new_node;
            }
            new_node->key_num++;
            // 清空原节点
            node->keys[i] = 0;
            node->children[i] = nullptr;
        }
        new_node->children[new_node->key_num] = node->children[M];
        if (node->children[M]) {
            node->children[M]->parent = new_node;
        }
        node->children[M] = nullptr;
        // 更新原节点关键字数
        node->key_num = split_pos;
    }
    return new_node;
}

// 插入调整(处理上溢)
void InsertAdjust(BPlusTree* tree, BPlusTreeNode* node) {
    while (node && node->key_num == M) {
        int split_pos = M / 2;
        int promoted_key;
        BPlusTreeNode* new_node;
        if (node->is_leaf) {
            // 叶子节点分裂
            new_node = SplitNode(tree, node);
            promoted_key = new_node->keys[0]; // 复制第一个关键字到父节点
        }
        else {
            // 内部节点分裂
            promoted_key = node->keys[split_pos];
            new_node = SplitNode(tree, node);
        }
        if (node->parent == nullptr) {
            // 创建新的根节点
            BPlusTreeNode* new_root = CreateNode(false);
            new_root->keys[0] = promoted_key;
            new_root->key_num = 1;
            new_root->children[0] = node;
            new_root->children[1] = new_node;
            node->parent = new_root;
            new_node->parent = new_root;
            tree->root = new_root;
            break;
        }
        else {
            // 插入到父节点
            BPlusTreeNode* parent = node->parent;
            int pos = FindKeyIndex(parent, promoted_key);
            // 移动关键字和指针
            for (int i = parent->key_num; i > pos; i--) {
                parent->keys[i] = parent->keys[i - 1];
                parent->children[i + 1] = parent->children[i];
            }
            parent->keys[pos] = promoted_key;
            parent->children[pos] = node;
            parent->children[pos + 1] = new_node;
            parent->key_num++;
            // 继续向上调整
            node = parent;
        }
    }
}

bool Delete(BPlusTree* tree, int key) {
    assert(tree != nullptr);
    if (tree->root == nullptr) {
        return false;
    }
    SearchResult* result = Search(tree, key);
    if (!result->found) {
        free(result);
        return false;
    }
    BPlusTreeNode* leaf = result->node;
    int pos = result->index;
    free(result);
    // 从叶子节点删除
    for (int i = pos; i < leaf->key_num - 1; i++) {
        leaf->keys[i] = leaf->keys[i + 1];
        leaf->data_ptrs[i] = leaf->data_ptrs[i + 1];
    }
    leaf->key_num--;
    tree->size--;
    // 如果是第一个关键字被删除,需要更新父节点
    if (pos == 0 && leaf->parent) {
        BPlusTreeNode* parent = leaf->parent;
        int parent_pos = FindKeyIndex(parent, key);
        if (parent_pos < parent->key_num && parent->keys[parent_pos] == key) {
            parent->keys[parent_pos] = leaf->keys[0];
        }
    }
    // 检查下溢
    if (leaf->key_num < (M + 1) / 2 - 1) {
        DeleteAdjust(tree, leaf);
    }
    return true;
}

// 删除调整(处理下溢)
void DeleteAdjust(BPlusTree* tree, BPlusTreeNode* node) {
    if (node == tree->root) {
        // 根节点特殊处理
        if (node->key_num == 0 && !node->is_leaf) {
            tree->root = node->children[0];
            if (tree->root) {
                tree->root->parent = nullptr;
            }
            free(node);
        }
        return;
    }
    // 计算最小关键字数
    int min_keys = (M + 1) / 2 - 1;
    if (node->key_num >= min_keys) {
        return;
    }
    BPlusTreeNode* parent = node->parent;
    int index = 0;
    while (parent->children[index] != node) {
        index++;
    }
    // 尝试从左兄弟借
    if (index > 0) {
        BPlusTreeNode* left_sibling = parent->children[index - 1];
        if (left_sibling->key_num > min_keys) {
            // 从左兄弟借一个元素
            if (node->is_leaf) {
                // 叶子节点借用
                for (int i = node->key_num; i > 0; i--) {
                    node->keys[i] = node->keys[i - 1];
                    node->data_ptrs[i] = node->data_ptrs[i - 1];
                }
                node->keys[0] = left_sibling->keys[left_sibling->key_num - 1];
                node->data_ptrs[0] = left_sibling->data_ptrs[left_sibling->key_num - 1];
                node->key_num++;
                left_sibling->key_num--;
                // 更新父节点关键字
                parent->keys[index - 1] = node->keys[0];
            }
            else {
                // 内部节点借用
                // 将父节点关键字下移
                for (int i = node->key_num; i > 0; i--) {
                    node->keys[i] = node->keys[i - 1];
                }
                for (int i = node->key_num + 1; i > 0; i--) {
                    node->children[i] = node->children[i - 1];
                }
                node->keys[0] = parent->keys[index - 1];
                node->children[0] = left_sibling->children[left_sibling->key_num];
                if (node->children[0]) {
                    node->children[0]->parent = node;
                }
                node->key_num++;
                // 将左兄弟最后一个关键字上移到父节点
                parent->keys[index - 1] = left_sibling->keys[left_sibling->key_num - 1];
                left_sibling->key_num--;
            }
            return;
        }
    }
    // 尝试从右兄弟借
    if (index < parent->key_num) {
        BPlusTreeNode* right_sibling = parent->children[index + 1];
        if (right_sibling->key_num > min_keys) {
            // 从右兄弟借一个元素
            if (node->is_leaf) {
                // 叶子节点借用
                node->keys[node->key_num] = right_sibling->keys[0];
                node->data_ptrs[node->key_num] = right_sibling->data_ptrs[0];
                node->key_num++;

                // 移动右兄弟的元素
                for (int i = 0; i < right_sibling->key_num - 1; i++) {
                    right_sibling->keys[i] = right_sibling->keys[i + 1];
                    right_sibling->data_ptrs[i] = right_sibling->data_ptrs[i + 1];
                }
                right_sibling->key_num--;

                // 更新父节点关键字
                parent->keys[index] = right_sibling->keys[0];
            }
            else {
                // 内部节点借用
                node->keys[node->key_num] = parent->keys[index];
                node->children[node->key_num + 1] = right_sibling->children[0];
                if (node->children[node->key_num + 1]) {
                    node->children[node->key_num + 1]->parent = node;
                }
                node->key_num++;

                // 将右兄弟第一个关键字上移到父节点
                parent->keys[index] = right_sibling->keys[0];

                // 移动右兄弟的元素
                for (int i = 0; i < right_sibling->key_num - 1; i++) {
                    right_sibling->keys[i] = right_sibling->keys[i + 1];
                }
                for (int i = 0; i < right_sibling->key_num; i++) {
                    right_sibling->children[i] = right_sibling->children[i + 1];
                }
                right_sibling->key_num--;
            }
            return;
        }
    }

    // 合并操作
    if (index > 0) {
        // 与左兄弟合并
        BPlusTreeNode* left_sibling = parent->children[index - 1];

        if (node->is_leaf) {
            // 叶子节点合并
            for (int i = 0; i < node->key_num; i++) {
                left_sibling->keys[left_sibling->key_num + i] = node->keys[i];
                left_sibling->data_ptrs[left_sibling->key_num + i] = node->data_ptrs[i];
            }
            left_sibling->key_num += node->key_num;
            left_sibling->next = node->next;

            // 删除父节点关键字
            for (int i = index - 1; i < parent->key_num - 1; i++) {
                parent->keys[i] = parent->keys[i + 1];
                parent->children[i + 1] = parent->children[i + 2];
            }
            parent->key_num--;
            free(node);
        }
        else {
            // 内部节点合并
            left_sibling->keys[left_sibling->key_num] = parent->keys[index - 1];
            left_sibling->key_num++;
            for (int i = 0; i < node->key_num; i++) {
                left_sibling->keys[left_sibling->key_num + i] = node->keys[i];
                left_sibling->children[left_sibling->key_num + i] = node->children[i];
                if (left_sibling->children[left_sibling->key_num + i]) {
                    left_sibling->children[left_sibling->key_num + i]->parent = left_sibling;
                }
            }
            left_sibling->children[left_sibling->key_num + node->key_num] = node->children[node->key_num];
            if (left_sibling->children[left_sibling->key_num + node->key_num]) {
                left_sibling->children[left_sibling->key_num + node->key_num]->parent = left_sibling;
            }
            left_sibling->key_num += node->key_num;

            // 删除父节点关键字
            for (int i = index - 1; i < parent->key_num - 1; i++) {
                parent->keys[i] = parent->keys[i + 1];
                parent->children[i + 1] = parent->children[i + 2];
            }
            parent->key_num--;
            free(node);
        }
    }
    else {
        // 与右兄弟合并
        BPlusTreeNode* right_sibling = parent->children[index + 1];

        if (node->is_leaf) {
            // 叶子节点合并
            for (int i = 0; i < right_sibling->key_num; i++) {
                node->keys[node->key_num + i] = right_sibling->keys[i];
                node->data_ptrs[node->key_num + i] = right_sibling->data_ptrs[i];
            }
            node->key_num += right_sibling->key_num;
            node->next = right_sibling->next;

            // 删除父节点关键字
            for (int i = index; i < parent->key_num - 1; i++) {
                parent->keys[i] = parent->keys[i + 1];
                parent->children[i + 1] = parent->children[i + 2];
            }
            parent->key_num--;

            free(right_sibling);
        }
        else {
            // 内部节点合并
            node->keys[node->key_num] = parent->keys[index];
            node->key_num++;

            for (int i = 0; i < right_sibling->key_num; i++) {
                node->keys[node->key_num + i] = right_sibling->keys[i];
                node->children[node->key_num + i] = right_sibling->children[i];
                if (node->children[node->key_num + i]) {
                    node->children[node->key_num + i]->parent = node;
                }
            }
            node->children[node->key_num + right_sibling->key_num] = right_sibling->children[right_sibling->key_num];
            if (node->children[node->key_num + right_sibling->key_num]) {
                node->children[node->key_num + right_sibling->key_num]->parent = node;
            }
            node->key_num += right_sibling->key_num;

            // 删除父节点关键字
            for (int i = index; i < parent->key_num - 1; i++) {
                parent->keys[i] = parent->keys[i + 1];
                parent->children[i + 1] = parent->children[i + 2];
            }
            parent->key_num--;

            free(right_sibling);
        }
    }
    // 递归向上调整
    DeleteAdjust(tree, parent);
}

// ==================== 显示和遍历函数 ====================
//显示
void Display(BPlusTree* tree, bool show_details) {
    assert(tree != nullptr);
    printf("B+ Tree (size: %d):\n", tree->size);
    DisplayNode(tree->root, 0, show_details);
    printf("\n");
}
void DisplayNode(BPlusTreeNode* node, int level, bool show_details) {
    if (node == nullptr) return;
    // 打印缩进
    for (int i = 0; i < level; i++) {
        printf("  ");
    }
    printf("[");
    for (int i = 0; i < node->key_num; i++) {
        printf("%d", node->keys[i]);
        if (i < node->key_num - 1) printf(", ");
    }
    printf("]");
    if (show_details) {
        printf(" (keys=%d, %s)", node->key_num,node->is_leaf ? "leaf" : "internal");
        if (node->is_leaf && node->next) {
            printf(" -> next");
        }
    }
    printf("\n");
    if (!node->is_leaf) {
        for (int i = 0; i <= node->key_num; i++) {
            DisplayNode(node->children[i], level + 1, show_details);
        }
    }
}

//范围查询
void RangeQuery(BPlusTree* tree, int start_key, int end_key) {
    assert(tree != nullptr);
    if (tree->root == nullptr) {
        printf("Tree is empty.\n");
        return;
    }
    // 查找起始关键字
    SearchResult* result = Search(tree, start_key);
    BPlusTreeNode* current = result->node;
    int pos = result->index;
    free(result);
    printf("Range query [%d, %d]: ", start_key, end_key);
    bool found_any = false;
    while (current) {
        while (pos < current->key_num) {
            if (current->keys[pos] > end_key) {
                printf("\n");
                return;
            }
            printf("%d ", current->keys[pos]);
            found_any = true;
            pos++;
        }
        current = current->next;
        pos = 0;
    }
    if (!found_any) {
        printf("No keys found in range.");
    }
    printf("\n");
}
//销毁树
void DestroyTree(BPlusTree* tree) {
    assert(tree != nullptr);
    DestroyNode(tree->root);
    tree->root = nullptr;
    tree->first_leaf = nullptr;
    tree->size = 0;
}
void DestroyNode(BPlusTreeNode* node) {
    if (node == nullptr) return;
    if (!node->is_leaf) {
        for (int i = 0; i <= node->key_num; i++) {
            DestroyNode(node->children[i]);
        }
    }
    free(node);
}
相关推荐
元亓亓亓2 小时前
LeetCode热题100--64. 最小路径和--中等
算法·leetcode·职场和发展
mit6.8242 小时前
回溯+位运算|前缀和优化背包
算法
努力学算法的蒟蒻2 小时前
day49(12.30)——leetcode面试经典150
算法·leetcode·面试
天赐学c语言2 小时前
12.30 - 合并区间 && C++中class和C语言中struct的区别
c语言·c++·算法·leecode
报错小能手2 小时前
数据结构 b树(b-)树
数据结构·b树
有一个好名字2 小时前
力扣-递增的三元子序列
算法·leetcode·职场和发展
陌路202 小时前
S31 B树详解
数据结构·b树
Boop_wu2 小时前
[Java 数据结构] 图(1)
数据结构·算法
无尽的罚坐人生3 小时前
hot 100 128. 最长连续序列
数据结构·算法·贪心算法