当前位置:   article > 正文

算法导论 第18章 B树_算法导论 b树

算法导论 b树

一、定义

1、B树

B树是为磁盘或其它直接存取辅助存储设备而设计的一种平衡查找树,主要特点是降低磁盘I/O操作次数。
B树以自然的方式推广二叉查找树。
B树的分支因子由磁盘特性所决定。 

2、B数的数据结构

int n:当前存储在结点x中的关键字数
key[N]:n个关键,以非降序存放
bool leaf;//TRUE:x是叶子;FALSE:x是内结点
node *child[N+1]:只有内结点才有。指向其n+1个孩子的指针。child[1].key <= key[1] <= child[2].key……

3.B树的特征

(1)只有内结点才有指向子女的指针,且child[1].key <= key[1] <= child[2].key……
(2)每个叶结点具有相同的深度
(3)分支因子t>=2
(4)每个非根结点至少有t-1个关键字,如果是内结点,至少有t个子女
(5)每个结点至多有2t-1个关键字,如果是内结点,到多有2t个子女

4.B树上的操作

B-Tree-Search(x, k)
B-Tree-Create(T)
B-Tree-Split-Child(x,i,y)
B-Tree-Insert(T,k)
B-Tree-Insert-Nonfull(x,k)
B-Tree-Delete(T,x)

二、代码

B_Tree.h

  1. #include <iostream>
  2. using namespace std;
  3. #define N 10
  4. int t = 2;
  5. //B树结点结构
  6. struct node
  7. {
  8. int n;//当前存储在结点x中的关键字数
  9. char key[N];//n个关键字,以非降序存放
  10. bool leaf;//TRUE:x是叶子;FALSE:x是内结点
  11. node *child[N+1];//指向其n+1个孩子的指针
  12. //构造函数
  13. node(int num, bool IsLeaf):n(num),leaf(IsLeaf){}
  14. //磁盘读写操作
  15. void Disk_Read(){}
  16. void Disk_Write(){}
  17. };
  18. //B树结构
  19. class B_Tree
  20. {
  21. public:
  22. //指向根结点
  23. node *root;
  24. B_Tree():root(NULL){}
  25. //从以x为根结点的树中寻找关键字为k的结点,若找到,将结果存入y中,返回其是第几个关键字
  26. int B_Tree_Search(node *x, char k, node&y);
  27. //构造一棵带树结点的空树
  28. void B_Tree_Create();
  29. //分裂,把y分裂为两个结点,选择其中一个关键字插入到x中的第i个位置
  30. void B_Tree_Split_Child(node *x, int i, node *y);
  31. //将关键字k插入到一个未满的结点x中
  32. void B_Tree_Insert_Nonfull(node *x, char k);
  33. //向T中插入关键字k
  34. void B_Tree_Insert(char k);
  35. //删除T树中关键字为k的结点,由于是递归方法,当前处理的是x结点
  36. void B_Tree_Delete(node *x, char k);
  37. //按关键字从小到大输出结点
  38. void Print(node *n);
  39. };
  40. //从以x为根结点的树中寻找关键字为k的结点,若找到,将结果存入y中,返回其是第几个关键字
  41. int B_Tree::B_Tree_Search(node *x, char k, node&y)
  42. {
  43. int i = 1;
  44. //找到第一个关键字不大于k的i
  45. while(i < x->n && k > x->key[i])
  46. i++;
  47. //若key[i] = k,则找到了
  48. if(i <= x->n && k == x->key[i])
  49. {
  50. //将结果存入y中
  51. y = *x;
  52. //返回其是第几个关键字
  53. return i;
  54. }
  55. //若没找到,则返回空
  56. if(x->leaf)
  57. {
  58. // &y = NULL;
  59. return 0;
  60. }
  61. //若还有子树可以找,则递归查找第i个子树
  62. x->child[i]->Disk_Read();
  63. return B_Tree_Search(x->child[i], k, y);
  64. }
  65. //构造一棵带树结点的空树
  66. void B_Tree::B_Tree_Create()
  67. {
  68. //生成一个根结点
  69. //初始时,根结点为叶子结点,根结点中没有关键字
  70. root = new node(0, true);
  71. root->Disk_Write();
  72. }
  73. //分裂,把y分裂为两个结点,选择其中一个关键字插入到x中的第i个位置
  74. void B_Tree::B_Tree_Split_Child(node *x, int i, node *y)
  75. {
  76. int j;
  77. //生成一个新结点z
  78. //要把y分裂为y和z,因此z的叶子属性与y相同
  79. //分裂前y有2t-1个关键字,分裂后前t-1个属于y,后t-1个属于z,中间第t个属于x
  80. node *z = new node(t-1, y->leaf);
  81. y->n = t - 1;
  82. //后t-1个关键字依次复制给z
  83. for(j = 1; j < t; j++)
  84. z->key[j] = y->key[j+t];
  85. //如果有孩子,孩子也要复制过去,原来有2t个子树,前t个属于y,后t个属于z
  86. if(y->leaf == false)
  87. {
  88. for(j = 1; j <= t; j++)
  89. z->child[j] = y->child[j+t];
  90. }
  91. //使z作为x的第i+1个孩子(y已经是x的第i个孩子)
  92. for(j = x->n+1; j > i; j--)
  93. x->child[j+1] = x->child[j];
  94. x->child[i+1] = z;
  95. //把y中第t个关键字插入到x的第i个位置
  96. for(j = x->n; j >= i; j--)
  97. x->key[j+1] = x->key[j];
  98. x->key[i] = y->key[t];
  99. //x的关键字+1
  100. x->n++;
  101. y->Disk_Write();
  102. z->Disk_Write();
  103. x->Disk_Write();
  104. }
  105. //将关键字k插入到一个未满的结点x中
  106. void B_Tree::B_Tree_Insert_Nonfull(node *x, char k)
  107. {
  108. int i = x->n;
  109. //若x是叶子结点
  110. if(x->leaf)
  111. {
  112. //找到该插入的位置
  113. while(i >= 1 && k < x->key[i])
  114. {
  115. x->key[i+1] = x->key[i];
  116. i--;
  117. }
  118. //插入关键字k
  119. x->key[i+1] = k;
  120. x->n++;
  121. x->Disk_Write();
  122. }
  123. //若不是叶子结点
  124. else
  125. {
  126. //找到该插入的位置
  127. while(i >= 1 && k < x->key[i])
  128. i--;
  129. i++;
  130. //读取其孩子,将关键字插入到它的孩子中,分两种情况
  131. x->child[i]->Disk_Read();
  132. //孩子已满
  133. if(x->child[i]->n == 2 * t - 1)
  134. {
  135. //对孩子执行分裂操作,分裂后,孩子不变为不满
  136. B_Tree_Split_Child(x, i, x->child[i]);
  137. if(k > x->key[i])
  138. i++;
  139. }
  140. //孩子不满,直接对孩子进行插入操作
  141. B_Tree_Insert_Nonfull(x->child[i], k);
  142. }
  143. }
  144. //向T中插入关键字k
  145. void B_Tree::B_Tree_Insert(char k)
  146. {
  147. node *r = root, *s;
  148. //若根结点已满
  149. if(r->n == 2*t-1)
  150. {
  151. //申请一个新的结点,将新的结点作为根结点
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/375461
推荐阅读
相关标签
  

闽ICP备14008679号