• 数据结构小记【Python/C++版】——B树篇


    一,基础概念

    B树也是一种自平衡搜索树,常用于数据库中索引的实现。

    B树和AVL树的区别在于:

    B树是一种多路平衡查找树,B树的节点可以有两个以上的子节点(AVL树是二叉树,最多只能有两个子节点)。

    B树的每个节点可以存储一个以上的数据域(在之前介绍过的树结构中,一个节点只有一个数据域)。由于B树的节点可以存放多条数据,因此B树特别适合应用在块存储的开发场景。

    B树和AVL树的相同点在于:

    B树的节点分布也是按照左小右大排列,子节点与节点的大小比较结果决定了子节点的位置。

    每个节点中,左子树的数据比当前节点都小,右子树的数据比当前节点都大。

    关于B树的阶:

    M阶B树表示该树每个节点最多有M个子树。若B树中一个节点的子节点数目的最大值为4,则该树为4阶。

    M阶B树可以定义为M路搜索树:

    节点的最多子节点数为M。

    节点的最大数据量为M-1。

    所有非叶子节点(根节点除外)应该至少有M/2个子节点。

    所有节点(根节点除外)应该至少有M/2-1条数据。

    B树的阶数可以帮助我们确定节点在B树中可以容纳的子节点数。如果B树的阶数为3,则子节点的最小数量为2,最大数量为3,节点最多可以存放2个数据。类似地,如果B树的阶数为4,则子节点的最小和最大数量将分别为2和4,节点最多可以存放3个数据。

    B树的基本结构:

    B树的结构特点:

    所有叶子节点都出现在同一水平高度。

    B树是一棵扁平树,层数很小,B树的节点不再只存储一条数据。

    B树节点内的所有数据必须按键值升序排列。

    B树的设计原则就是,将尽可能多的数据放入B树的每个节点中,从而使B树的层数保持在最小值。由于不用遍历很多层节点,与其他平衡树相比,B树的访问速度更快。

    二,B树的基本操作

    搜索节点:

    节点在B树中的搜索步骤与BST树中的类似。

    插入节点:

    如果树为空,则创建一个新节点并将其作为根节点插入到树中。

    如果树不为空,插入节点包含两个操作:

    1.搜索合适的位置以插入节点

    按照升序插入节点。

    2.当节点的数据量过大时拆分节点

    插入新节点以后,节点中数据的数量超过了限制(节点的最大数据量为M-1),则按中位数拆分。将中间节点推往上一层,使左边节点成为左子节点,右边节点成为右子节点。

    图示样例:

    三,完整代码实现

    C++实现:

    1. #include
    2. using namespace std;
    3. class Node {
    4. int* keys;
    5. int t;
    6. Node** C;
    7. int n;
    8. bool leaf;
    9. public:
    10. Node(int _t, bool _leaf);
    11. void insertNonFull(int k);
    12. void splitChild(int i, Node* y);
    13. void traverse();
    14. friend class BTree;
    15. };
    16. class BTree {
    17. Node* root;
    18. int t;
    19. public:
    20. BTree(int _t) {
    21. root = NULL;
    22. t = _t;
    23. }
    24. void traverse() {
    25. if (root != NULL)
    26. root->traverse();
    27. }
    28. void insert(int k);
    29. };
    30. Node::Node(int t1, bool leaf1) {
    31. t = t1;
    32. leaf = leaf1;
    33. keys = new int[2 * t - 1];
    34. C = new Node * [2 * t];
    35. n = 0;
    36. }
    37. //遍历节点
    38. void Node::traverse() {
    39. int i;
    40. for (i = 0; i < n; i++) {
    41. if (leaf == false)
    42. C[i]->traverse();
    43. cout << " " << keys[i];
    44. }
    45. if (leaf == false)
    46. C[i]->traverse();
    47. }
    48. void BTree::insert(int k) {
    49. if (root == NULL) {
    50. root = new Node(t, true);
    51. root->keys[0] = k;
    52. root->n = 1;
    53. }
    54. else {
    55. if (root->n == 2 * t - 1) {
    56. Node* s = new Node(t, false);
    57. s->C[0] = root;
    58. s->splitChild(0, root);
    59. int i = 0;
    60. if (s->keys[0] < k)
    61. i++;
    62. s->C[i]->insertNonFull(k);
    63. root = s;
    64. }
    65. else
    66. root->insertNonFull(k);
    67. }
    68. }
    69. void Node::insertNonFull(int k) {
    70. int i = n - 1;
    71. if (leaf == true) {
    72. while (i >= 0 && keys[i] > k) {
    73. keys[i + 1] = keys[i];
    74. i--;
    75. }
    76. keys[i + 1] = k;
    77. n = n + 1;
    78. }
    79. else {
    80. while (i >= 0 && keys[i] > k)
    81. i--;
    82. if (C[i + 1]->n == 2 * t - 1) {
    83. splitChild(i + 1, C[i + 1]);
    84. if (keys[i + 1] < k)
    85. i++;
    86. }
    87. C[i + 1]->insertNonFull(k);
    88. }
    89. }
    90. //拆分节点
    91. void Node::splitChild(int i, Node* y) {
    92. Node* z = new Node(y->t, y->leaf);
    93. z->n = t - 1;
    94. for (int j = 0; j < t - 1; j++)
    95. z->keys[j] = y->keys[j + t];
    96. if (y->leaf == false) {
    97. for (int j = 0; j < t; j++)
    98. z->C[j] = y->C[j + t];
    99. }
    100. y->n = t - 1;
    101. for (int j = n; j >= i + 1; j--)
    102. C[j + 1] = C[j];
    103. C[i + 1] = z;
    104. for (int j = n - 1; j >= i; j--)
    105. keys[j + 1] = keys[j];
    106. keys[i] = y->keys[t - 1];
    107. n = n + 1;
    108. }
    109. int main() {
    110. BTree t(3);
    111. t.insert(8);
    112. t.insert(9);
    113. t.insert(10);
    114. t.insert(11);
    115. t.insert(15);
    116. t.insert(20);
    117. t.insert(17);
    118. cout << "The B-tree is: ";
    119. t.traverse();
    120. }

    运行结果:

    The B-tree is:  8 9 10 11 15 17 20

    Python实现:

    1. class BTreeNode:
    2. def __init__(self, leaf=False):
    3. self.leaf = leaf
    4. self.keys = []
    5. self.child = []
    6. class BTree:
    7. def __init__(self, t):
    8. self.root = BTreeNode(True)
    9. self.t = t
    10. def insert(self, k):
    11. root = self.root
    12. if len(root.keys) == (2 * self.t) - 1:
    13. temp = BTreeNode()
    14. self.root = temp
    15. temp.child.insert(0, root)
    16. self.split_child(temp, 0)
    17. self.insert_non_full(temp, k)
    18. else:
    19. self.insert_non_full(root, k)
    20. def insert_non_full(self, x, k):
    21. i = len(x.keys) - 1
    22. if x.leaf:
    23. x.keys.append((None, None))
    24. while i >= 0 and k[0] < x.keys[i][0]:
    25. x.keys[i + 1] = x.keys[i]
    26. i -= 1
    27. x.keys[i + 1] = k
    28. else:
    29. while i >= 0 and k[0] < x.keys[i][0]:
    30. i -= 1
    31. i += 1
    32. if len(x.child[i].keys) == (2 * self.t) - 1:
    33. self.split_child(x, i)
    34. if k[0] > x.keys[i][0]:
    35. i += 1
    36. self.insert_non_full(x.child[i], k)
    37. def split_child(self, x, i):
    38. t = self.t
    39. y = x.child[i]
    40. z = BTreeNode(y.leaf)
    41. x.child.insert(i + 1, z)
    42. x.keys.insert(i, y.keys[t - 1])
    43. z.keys = y.keys[t: (2 * t) - 1]
    44. y.keys = y.keys[0: t - 1]
    45. if not y.leaf:
    46. z.child = y.child[t: 2 * t]
    47. y.child = y.child[0: t - 1]
    48. def print_tree(self, x, l=0):
    49. print("Level ", l, " ", len(x.keys), end=":")
    50. for i in x.keys:
    51. print(i, end=" ")
    52. print()
    53. l += 1
    54. if len(x.child) > 0:
    55. for i in x.child:
    56. self.print_tree(i, l)
    57. def main():
    58. B = BTree(3)
    59. for i in range(10):
    60. B.insert((i, 2 * i))
    61. B.print_tree(B.root)
    62. if __name__ == '__main__':
    63. main()

    四,参考阅读

    https://iq.opengenus.org/b-tree-searching-insertion/

    https://www.programiz.com/dsa/insertion-into-a-b-tree

    https://www.programiz.com/dsa/b-plus-tree

  • 相关阅读:
    初试占比70%,计算机招生近200人,安徽理工大学考情分析
    二叉树(堆)
    c语言学习记录 c语言本身有什么
    Vue3 Composition API(案例)
    Nginx开启Brotli
    杀疯了,GitHub疯传2022Java面试八股文解析+大厂面试攻略
    怎么样深入学习一门技术(Python)
    坤坤的加法
    2022 CCF BDCI 返乡发展人群预测 [0.9117+]
    MetaTown:一个可以自己构建数字资产的平台
  • 原文地址:https://blog.csdn.net/CoderZZ_2024/article/details/136521785