330-B树的查询和插入

我就是我 2022-10-05 01:53 130阅读 0赞

B树的静态索引

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

动态搜索结构

在这里插入图片描述
n是当前结点关键码的个数
Ki代表多个关键码,从小到大排序。
如果P1有子树,子树的所有关键码均大于K2小于K2。
子树的特点:
在这里插入图片描述

如何建立B树

在这里插入图片描述
(自平衡树)
在这里插入图片描述
B树的结点结构
在这里插入图片描述
data的下标1,2,3,4,用于存放数据,0下标是哨兵位,5下标用于分裂
data下标1,2,3,4的存放的关键码依次增大
sub分枝的下标0,1,2,3,4,用于存放分枝

可以看做二叉树。上面的数据(关键码)代表双亲。其关键码大于左孩子而小于右孩子
相当于二叉排序树
如果有左分枝,必要有右分枝。关键码的左右都必须要有分枝
在这里插入图片描述

  1. #include<iostream>
  2. using namespace std;
  3. #define M 5 //分路数
  4. #define MINITEM (M/2) // 最小分枝数 >=2
  5. #define MAXITEM (M-1) //最大分枝数
  6. typedef char KeyType;
  7. typedef struct {
  8. } Record;//记录集
  9. typedef struct
  10. {
  11. KeyType key;//关键码
  12. Record* recptr;//元素类型
  13. }ElemType;// key_value
  14. struct BNode
  15. {
  16. int num;//元素的个数
  17. BNode* parent;//双亲的指针
  18. ElemType data[M + 1];//元素的个数,相当于下标0,1,2,3,4,5,0下标是哨兵位,5下标是分裂用的
  19. BNode* sub[M + 1];//分枝数,0,1,2,3,4,5
  20. };//B树的结点结构
  21. typedef struct
  22. {
  23. BNode* root;//根节点
  24. int cursize;//当前B树的结点个数
  25. }BTree;
  26. BNode* Buynode()//购买节点
  27. {
  28. BNode* s = (BNode*)malloc(sizeof(BNode));
  29. if (s == nullptr) exit(1);
  30. memset(s, 0, sizeof(BNode));
  31. return s;
  32. }
  33. void Freenode(BNode* p)//释放结点
  34. {
  35. free(p);
  36. }

建立B树图(查询,创建)

n是元素的个数,p代表双亲
d是data,s是sub
购买的结点构造如下
在这里插入图片描述
d是key_value,s是分枝

如果我们进行数据的插入
不断插入下列数据

在这里插入图片描述
我们先插入g,是空树,购买一个结点,g插入到data的1号位置。
在这里插入图片描述
我们插入k,要先进行查询,树中有没有这个k,所以查询就是首先把k放到哨兵位(d[0]),进行查询,拿k和g比较,k>g,在1号位置之后插入,也就是插入到2号位置。
在这里插入图片描述

当前,我们的个数是2,最大个数不能超过4。现在是OK的。
我们接着插入数据m,首先把m放到哨兵位,因为当前个数是2,所以从2下标开始比较,m大于k,我们把m放在3号位置。
在这里插入图片描述
我们再接着插入o,首先把o放到哨兵位,因为当前个数是3,所以从3号位置进行比较,o大于m,o放到4号位置,当前个数就是4了。n=4。
在这里插入图片描述
如果我们接着要插入e,把e放入哨兵位,因为当前个数是4,从4号位置开始和o比较,小于o,m,k,g,然后e和e相等,停下来了。我们看s0分枝空不空,如果不空,在分枝下面查,如果是空,则没有查到,e在0位置之后(1号位置)插入,其他的数据后移,n=5了,超过最大个数了,根节点root指向了当前这个结点(如下图)。要进行分裂了。
在这里插入图片描述

分裂的时候要遵循下面3点
在这里插入图片描述
首先购买一个节点,从第3位开始,m/2=2,2+1=3。k,m,o移到新节点的0,1,2
在这里插入图片描述
左右边的数据都是2个。第0里面的不算。
双亲都为空。
再购买一个节点作为根节点。
把k从0位置提到双亲结点的1号位置。
根节点root指向这个新的双亲结点。

在这里插入图片描述
我们再插入s。首先把s放到哨兵位,
在这里插入图片描述
因为当前根节点的个数是1,所以从1号位置开始比较,s大于k,我们看分枝s1空不空,不空,把s再放到哨兵位,
在这里插入图片描述
当前节点的元素个数是2,s从2号位置开始进行比较查询,s大于o,在2号位置之后插入数据,当前节点的个数是3。
在这里插入图片描述
我们再接着插入a
把a放在根节点的哨兵位,当前根节点的个数1,在1号位置比较,a小于k,和0号位置比较,a==a,看s0分枝空不空,不空,把a放在哨兵位,再查找,a小于g,e.等于a。s0是空的,我们把a插入到0位置之后,其他数据后移。当前个数是3。
在这里插入图片描述
我们再插入d,把d放到哨兵位,d小于k,d=d,我们看s0分枝空不空,不空,把d放到哨兵位,d从3位置比较,小于g,e,大于a,我们看分枝s1空不空,空!把数据后移,把d插入到2号位置。
在这里插入图片描述
我们再插入f,首先把f放到根节点的哨兵位,f小于k,f=f,在s0里面查询,放到哨兵位,f小于g,大于e,看s3空不空,空的,只能数据后移,f到4号位置。当前个数是5,超出范围,要进行分裂。我们再购买一个节点。
在这里插入图片描述
把efg移动到新的节点的0,1,2位置。都是同一个双亲。e给双亲,e和k比较,小于k,e=e,k后移,e在1号位置。然后分枝如下
在这里插入图片描述
如果我们插入c,c放在根节点的哨兵位,c小于k,e,c=c,s0不空,我们把c再放入哨兵位,查找,小于d,大于a,子树是空,d后移,我们把c插入到2号位置,
在这里插入图片描述
我们插入b,放到根节点的哨兵位进行查询,有2个数据,b小于k,e,b=b,我们看s0不空,放到哨兵位查询,b小于d,c,大于a,子树为空,c和d后移,在2号位置插入b,
在这里插入图片描述
我们再次插入数据h。
在这里插入图片描述
我们插入q,放到根节点的哨兵位,大于k,从s2查询,放到哨兵位,q小于s,大于o,s往后移,q放在3号位置。变成4个数据了。
在这里插入图片描述
我们再插入p,p大于k,和s比较,小于s,q,大于o,q,s后移,p放在3号位置,变成5个数据了。超出范围,进行分裂,购买一个兄弟结点。pqs移动到新结点的0,1,2,
在这里插入图片描述
我们把p往双亲走,大于k,p放在3号位置。
在这里插入图片描述
3结点4分枝。
我们再插入j,小于p,k,大于e,是s1分枝找,j大于h,放在4号位置。当前4个数据。
在这里插入图片描述
我们插入i,i小于p,k,i大于e,在s1查询,小于j,大于h,插入,已经5个数据了,要分裂。所以购买一个兄弟结点。hij移动到新结点的0,1,2
在这里插入图片描述
把h给双亲,小于p,k,大于e,k,p后移,sub也移动,4个数据5分枝。
在这里插入图片描述
等价下图
在这里插入图片描述

连级分裂

在这里插入图片描述
我们再插入z,大于p,走到s4的地方,大于s,插入s后面。
我们再插入x,大于p,走到s4的地方,小于z,大于s,插入进来。
在这里插入图片描述
我们再插入y,大于p,走到s4的地方,小于z大于x,插入,超过了最大元素的个数,要分裂,把xyz放到新结点的0,1,2,把x提到双亲,放在p的后面,5个数据6个分枝,根超出了!!!
在这里插入图片描述
我们再购买结点,我们把k,p,x放到新结点的0,1,2,3数据3分枝。
在这里插入图片描述
双亲为空,再建立一个结点,k放上去,在1位置,
在这里插入图片描述

B树的found查询函数

  1. typedef struct
  2. {
  3. BNode* pnode;//指向一个结点
  4. int index;//查找的结点在哪个位置
  5. bool tag;//true;//false
  6. }Result;
  7. Result Find_Key(BTree* ptree, KeyType kx)
  8. {
  9. Result res = {
  10. nullptr,-1,false };//初始化
  11. BNode* p = ptree->root;
  12. while (p != nullptr)
  13. {
  14. p->data[0].key = kx;
  15. int i = p->num;
  16. while (kx < p->data[i].key) --i;
  17. res.pnode = p;
  18. res.index = i;
  19. if (i > 0 && kx == p->data[i].key)
  20. {
  21. res.tag = true;
  22. break;
  23. }
  24. p=p->sub[i];
  25. }
  26. return res;
  27. }

B树的初始化,插入函数

  1. void Init_BTree(BTree* ptree)
  2. {
  3. assert(ptree != nullptr);
  4. ptree->root = nullptr;
  5. ptree->cursize = 0;
  6. }
  7. void Insert_Item(BNode* ptr, int pos, ElemType item, BNode* right)
  8. {
  9. for (int i = ptr->num; i > pos; --i)
  10. {
  11. ptr->data[i + 1] = ptr->data[i];
  12. ptr->sub[i + 1] = ptr->sub[i];
  13. }
  14. ptr->data[pos + 1] = item;
  15. ptr->sub[pos + 1] = right;
  16. if (right != nullptr) right->parent = ptr;
  17. ptr->num + -1;
  18. }
  19. ElemType Move_Right(BNode* ptr, BNode* right)
  20. {
  21. for (int j = 0, i = MINITEM + 1; i <= ptr->num; ++i, ++j)
  22. {
  23. right->data[j] = ptr->data[i];
  24. right->sub[j] = ptr->sub[i];
  25. if (right->sub[j] != nullptr)
  26. {
  27. right->sub[j]->parent = right;
  28. }
  29. }
  30. ptr->num = MINITEM;
  31. right->num = MINITEM;
  32. right->parent = ptr->parent;
  33. return right->data[0];
  34. }
  35. BNode* MakeRoot(BNode* left, BNode* right, ElemType item)
  36. {
  37. BNode* newroot = Buynode();
  38. newroot->data[1] = item;
  39. newroot->sub[0] = left;
  40. if (left != nullptr) left->parent = newroot;
  41. newroot->sub[1] = right;
  42. if (right != nullptr) right->parent = newroot;
  43. newroot->num = 1;
  44. newroot->parent = nullptr;
  45. return newroot;
  46. }
  47. BNode* Splice(BNode* ptr)
  48. {
  49. BNode* right = Buynode();
  50. ElemType item = Move_Right(ptr, right);
  51. if (ptr->parent == nullptr)
  52. {
  53. return MakeRoot(ptr, right, item);
  54. }
  55. BNode* pa = ptr->parent;
  56. int pos = pa->num;
  57. pa->data[0] = item;
  58. while (item.key < pa->data[pos].key) --pos;
  59. Insert_Item(pa, pos, item, right);
  60. if (pa->num > MAXITEM)
  61. {
  62. return Splice(pa);
  63. }
  64. else
  65. {
  66. return nullptr;
  67. }
  68. }
  69. bool Insert(BTree* ptree, ElemType item)
  70. {
  71. assert(ptree != nullptr);
  72. if (ptree->root == nullptr)
  73. {
  74. ptree->root = MakeRoot(NULL, NULL, item);
  75. return true;
  76. }
  77. Result res = Find_Key(ptree, item.key);
  78. if (res.tag) return false;
  79. BNode* p = res.pnode;
  80. int pos = res.index;
  81. Insert_Item(p, pos, item, nullptr);
  82. if (p->num > MAXITEM)
  83. {
  84. BNode* newroot = Splice(p);
  85. if (newroot != nullptr)
  86. {
  87. ptree->root = newroot;
  88. }
  89. }
  90. ptree->cursize += 1;
  91. return true;
  92. }

书写主函数检测

  1. #include<iostream>
  2. #include<assert.h>
  3. using namespace std;
  4. #define M 5 //分路数
  5. #define MINITEM (M/2) // 最小分枝数 >=2
  6. #define MAXITEM (M-1) //最大分枝数
  7. typedef char KeyType;
  8. typedef struct {
  9. } Record;//记录集
  10. typedef struct
  11. {
  12. KeyType key;//关键码
  13. Record* recptr;//元素类型
  14. }ElemType;// key_value
  15. struct BNode
  16. {
  17. int num;//元素的个数
  18. BNode* parent;//双亲的指针
  19. ElemType data[M + 1];//元素的个数,相当于下标0,1,2,3,4,5,0下标是哨兵位,5下标是分裂用的
  20. BNode* sub[M + 1];//分枝数,0,1,2,3,4,5
  21. };//B树的结点结构
  22. typedef struct
  23. {
  24. BNode* root;//根节点
  25. int cursize;//当前B树的结点个数
  26. }BTree;
  27. typedef struct
  28. {
  29. BNode* pnode;//指向一个结点
  30. int index;//查找的结点在哪个位置
  31. bool tag;//true;//false
  32. }Result;
  33. BNode* Buynode()//购买节点
  34. {
  35. BNode* s = (BNode*)malloc(sizeof(BNode));
  36. if (s == nullptr) exit(1);
  37. memset(s, 0, sizeof(BNode));
  38. return s;
  39. }
  40. void Freenode(BNode* p)//释放结点
  41. {
  42. free(p);
  43. }
  44. Result Find_Key(BTree* ptree, KeyType kx)
  45. {
  46. Result res = {
  47. nullptr,-1,false };//初始化
  48. BNode* p = ptree->root;
  49. while (p != nullptr)
  50. {
  51. p->data[0].key = kx;
  52. int i = p->num;
  53. while (kx < p->data[i].key) --i;
  54. res.pnode = p;
  55. res.index = i;
  56. if (i > 0 && kx == p->data[i].key)
  57. {
  58. res.tag = true;
  59. break;
  60. }
  61. p=p->sub[i];
  62. }
  63. return res;
  64. }
  65. void Init_BTree(BTree* ptree)
  66. {
  67. assert(ptree != nullptr);
  68. ptree->root = nullptr;
  69. ptree->cursize = 0;
  70. }
  71. void Insert_Item(BNode* ptr, int pos, ElemType item, BNode* right)
  72. {
  73. for (int i = ptr->num; i > pos; --i)
  74. {
  75. ptr->data[i + 1] = ptr->data[i];
  76. ptr->sub[i + 1] = ptr->sub[i];
  77. }
  78. ptr->data[pos + 1] = item;
  79. ptr->sub[pos + 1] = right;
  80. if (right != nullptr) right->parent = ptr;
  81. ptr->num +=1;
  82. }
  83. ElemType Move_Right(BNode* ptr, BNode* right)
  84. {
  85. for (int j = 0, i = MINITEM + 1; i <= ptr->num; ++i, ++j)
  86. {
  87. right->data[j] = ptr->data[i];
  88. right->sub[j] = ptr->sub[i];
  89. if (right->sub[j] != nullptr)
  90. {
  91. right->sub[j]->parent = right;
  92. }
  93. }
  94. ptr->num = MINITEM;
  95. right->num = MINITEM;
  96. right->parent = ptr->parent;
  97. return right->data[0];
  98. }
  99. BNode* MakeRoot(BNode* left, BNode* right, ElemType item)
  100. {
  101. BNode* newroot = Buynode();
  102. newroot->data[1] = item;
  103. newroot->sub[0] = left;
  104. if (left != nullptr) left->parent = newroot;
  105. newroot->sub[1] = right;
  106. if (right != nullptr) right->parent = newroot;
  107. newroot->num = 1;
  108. newroot->parent = nullptr;
  109. return newroot;
  110. }
  111. BNode* Splice(BNode* ptr)
  112. {
  113. BNode* right = Buynode();
  114. ElemType item = Move_Right(ptr, right);
  115. if (ptr->parent == nullptr)
  116. {
  117. return MakeRoot(ptr, right, item);
  118. }
  119. BNode* pa = ptr->parent;
  120. int pos = pa->num;
  121. pa->data[0] = item;
  122. while (item.key < pa->data[pos].key) --pos;
  123. Insert_Item(pa, pos, item, right);
  124. if (pa->num > MAXITEM)
  125. {
  126. return Splice(pa);
  127. }
  128. else
  129. {
  130. return nullptr;
  131. }
  132. }
  133. bool Insert(BTree* ptree, ElemType item)
  134. {
  135. assert(ptree != nullptr);
  136. if (ptree->root == nullptr)
  137. {
  138. ptree->root = MakeRoot(NULL, NULL, item);
  139. ptree->cursize+=1;
  140. return true;
  141. }
  142. Result res = Find_Key(ptree, item.key);
  143. if (res.tag) return false;
  144. BNode* p = res.pnode;
  145. int pos = res.index;
  146. Insert_Item(p, pos, item, nullptr);
  147. if (p->num > MAXITEM)
  148. {
  149. BNode* newroot = Splice(p);
  150. if (newroot != nullptr)
  151. {
  152. ptree->root = newroot;
  153. }
  154. }
  155. ptree->cursize += 1;
  156. return true;
  157. }
  158. int main()
  159. {
  160. char str[] = {
  161. "qwertyuiopasdfghjklkzxcvbnm" };
  162. int len = strlen(str);
  163. BTree myt;
  164. Init_BTree(&myt);
  165. for (int i = 0; i < len; ++i)
  166. {
  167. ElemType item = {
  168. str[i],nullptr };
  169. cout << Insert(&myt, item);
  170. }
  171. Result res = Find_Key(&myt, 'x');
  172. return 0;
  173. }

在这里插入图片描述

B树的中序遍历

在这里插入图片描述
中序遍历
abcdefghijkmopqsxyz
2数据3分枝

  1. void InOrder(BNode* p)
  2. {
  3. if (p == nullptr) return;
  4. InOrder(p->sub[0]);
  5. for (int i = 1; i <= p->num; ++i)
  6. {
  7. cout << p->data[i].key << " ";
  8. InOrder(p->sub[i]);
  9. }
  10. }
  11. void Inorder_BTree(BTree* ptree)
  12. {
  13. assert(ptree != nullptr);
  14. InOrder(ptree->root);
  15. cout << endl;
  16. }

主函数如下

  1. int main()
  2. {
  3. char str[] = {
  4. "qwertyuiopasdfghjklkzxcvbnm" };
  5. int len = strlen(str);
  6. BTree myt;
  7. Init_BTree(&myt);
  8. for (int i = 0; i < len; ++i)
  9. {
  10. ElemType item = {
  11. str[i],nullptr };
  12. cout << Insert(&myt, item);
  13. }
  14. Inorder_BTree(&myt);
  15. Result res = Find_Key(&myt, 'x');
  16. return 0;
  17. }

运行截图如下

在这里插入图片描述

发表评论

表情:
评论列表 (有 0 条评论,130人围观)

还没有评论,来说两句吧...

相关阅读

    相关 BB+B*

    一 B树的介绍 B-tree树即B树,B即Balanced,平衡的意思。有人把B-tree翻译成B-树,容易让人产生误解。会以为B-树是一种树,而B树又是另一种树。实际上