b树的作用是什么?做索引?索引可以用hash,红黑树O(logn),B-树,为什么数据库索引用B树呢?多叉树有许多,但是B树较为规范,使用方便。
    二叉树有天然的弊病:层数高,1024个节点二叉树需要10层。二叉树无法约束它的层高。但是B树层高比二叉树低,访问磁盘的次数比二叉树少。
    B树和红黑树的动态操作的最坏时间复杂度都是O(logn)那么二者区别在哪?在于B树能容纳更多的数据,并且B树的高度是可以控制的,而二叉树是不可以的,B树能更加方便得让子节点存放在硬盘。所以B树能减少机械磁盘的磁头跳转的次数,B树更加适合大量数据动态操作(很多数据库使用B+树来实现存储和检索)。

    B树是在多叉树的基础上加上了约束。
    B树的定义:
    image.png
    B树怎么写?

    1. #include <stdio.h>
    2. #include <stdlib.h>
    3. #include <string.h>
    4. #include <assert.h>
    5. #define DEGREE 3
    6. typedef int KEY_VALUE;
    7. typedef struct _btree_node {
    8. KEY_VALUE *keys;
    9. struct _btree_node **childrens;
    10. int num;
    11. int leaf;
    12. } btree_node;
    13. typedef struct _btree {
    14. btree_node *root;
    15. int t;
    16. } btree;
    17. btree_node *btree_create_node(int t, int leaf) {
    18. btree_node *node = (btree_node*)calloc(1, sizeof(btree_node));
    19. if (node == NULL) assert(0);
    20. node->leaf = leaf;
    21. node->keys = (KEY_VALUE*)calloc(1, (2*t-1)*sizeof(KEY_VALUE));
    22. node->childrens = (btree_node**)calloc(1, (2*t) * sizeof(btree_node));
    23. node->num = 0;
    24. return node;
    25. }
    26. void btree_destroy_node(btree_node *node) {
    27. assert(node);
    28. free(node->childrens);
    29. free(node->keys);
    30. free(node);
    31. }
    32. void btree_create(btree *T, int t) {
    33. T->t = t;
    34. btree_node *x = btree_create_node(t, 1);
    35. T->root = x;
    36. }
    37. void btree_split_child(btree *T, btree_node *x, int i) {
    38. int t = T->t;
    39. btree_node *y = x->childrens[i];
    40. btree_node *z = btree_create_node(t, y->leaf);
    41. z->num = t - 1;
    42. int j = 0;
    43. for (j = 0;j < t-1;j ++) {
    44. z->keys[j] = y->keys[j+t];
    45. }
    46. if (y->leaf == 0) {
    47. for (j = 0;j < t;j ++) {
    48. z->childrens[j] = y->childrens[j+t];
    49. }
    50. }
    51. y->num = t - 1;
    52. for (j = x->num;j >= i+1;j --) {
    53. x->childrens[j+1] = x->childrens[j];
    54. }
    55. x->childrens[i+1] = z;
    56. for (j = x->num-1;j >= i;j --) {
    57. x->keys[j+1] = x->keys[j];
    58. }
    59. x->keys[i] = y->keys[t-1];
    60. x->num += 1;
    61. }
    62. void btree_insert_nonfull(btree *T, btree_node *x, KEY_VALUE k) {
    63. int i = x->num - 1;
    64. if (x->leaf == 1) {
    65. while (i >= 0 && x->keys[i] > k) {
    66. x->keys[i+1] = x->keys[i];
    67. i --;
    68. }
    69. x->keys[i+1] = k;
    70. x->num += 1;
    71. } else {
    72. while (i >= 0 && x->keys[i] > k) i --;
    73. if (x->childrens[i+1]->num == (2*(T->t))-1) {
    74. btree_split_child(T, x, i+1);
    75. if (k > x->keys[i+1]) i++;
    76. }
    77. btree_insert_nonfull(T, x->childrens[i+1], k);
    78. }
    79. }
    80. void btree_insert(btree *T, KEY_VALUE key) {
    81. //int t = T->t;
    82. btree_node *r = T->root;
    83. if (r->num == 2 * T->t - 1) {
    84. btree_node *node = btree_create_node(T->t, 0);
    85. T->root = node;
    86. node->childrens[0] = r;
    87. btree_split_child(T, node, 0);
    88. int i = 0;
    89. if (node->keys[0] < key) i++;
    90. btree_insert_nonfull(T, node->childrens[i], key);
    91. } else {
    92. btree_insert_nonfull(T, r, key);
    93. }
    94. }
    95. void btree_traverse(btree_node *x) {
    96. int i = 0;
    97. for (i = 0;i < x->num;i ++) {
    98. if (x->leaf == 0)
    99. btree_traverse(x->childrens[i]);
    100. printf("%C ", x->keys[i]);
    101. }
    102. if (x->leaf == 0) btree_traverse(x->childrens[i]);
    103. }
    104. void btree_print(btree *T, btree_node *node, int layer)
    105. {
    106. btree_node* p = node;
    107. int i;
    108. if(p){
    109. printf("\nlayer = %d keynum = %d is_leaf = %d\n", layer, p->num, p->leaf);
    110. for(i = 0; i < node->num; i++)
    111. printf("%c ", p->keys[i]);
    112. printf("\n");
    113. #if 0
    114. printf("%p\n", p);
    115. for(i = 0; i <= 2 * T->t; i++)
    116. printf("%p ", p->childrens[i]);
    117. printf("\n");
    118. #endif
    119. layer++;
    120. for(i = 0; i <= p->num; i++)
    121. if(p->childrens[i])
    122. btree_print(T, p->childrens[i], layer);
    123. }
    124. else printf("the tree is empty\n");
    125. }
    126. int btree_bin_search(btree_node *node, int low, int high, KEY_VALUE key) {
    127. int mid;
    128. if (low > high || low < 0 || high < 0) {
    129. return -1;
    130. }
    131. while (low <= high) {
    132. mid = (low + high) / 2;
    133. if (key > node->keys[mid]) {
    134. low = mid + 1;
    135. } else {
    136. high = mid - 1;
    137. }
    138. }
    139. return low;
    140. }
    141. //{child[idx], key[idx], child[idx+1]}
    142. void btree_merge(btree *T, btree_node *node, int idx) {
    143. btree_node *left = node->childrens[idx];
    144. btree_node *right = node->childrens[idx+1];
    145. int i = 0;
    146. /////data merge
    147. left->keys[T->t-1] = node->keys[idx];
    148. for (i = 0;i < T->t-1;i ++) {
    149. left->keys[T->t+i] = right->keys[i];
    150. }
    151. if (!left->leaf) {
    152. for (i = 0;i < T->t;i ++) {
    153. left->childrens[T->t+i] = right->childrens[i];
    154. }
    155. }
    156. left->num += T->t;
    157. //destroy right
    158. btree_destroy_node(right);
    159. //node
    160. for (i = idx+1;i < node->num;i ++) {
    161. node->keys[i-1] = node->keys[i];
    162. node->childrens[i] = node->childrens[i+1];
    163. }
    164. node->childrens[i+1] = NULL;
    165. node->num -= 1;
    166. if (node->num == 0) {
    167. T->root = left;
    168. btree_destroy_node(node);
    169. }
    170. }
    171. void btree_delete_key(btree *T, btree_node *node, KEY_VALUE key) {
    172. if (node == NULL) return ;
    173. int idx = 0, i;
    174. while (idx < node->num && key > node->keys[idx]) {
    175. idx ++;
    176. }
    177. if (idx < node->num && key == node->keys[idx]) {
    178. if (node->leaf) {
    179. for (i = idx;i < node->num-1;i ++) {
    180. node->keys[i] = node->keys[i+1];
    181. }
    182. node->keys[node->num - 1] = 0;
    183. node->num--;
    184. if (node->num == 0) { //root
    185. free(node);
    186. T->root = NULL;
    187. }
    188. return ;
    189. } else if (node->childrens[idx]->num >= T->t) {
    190. btree_node *left = node->childrens[idx];
    191. node->keys[idx] = left->keys[left->num - 1];
    192. btree_delete_key(T, left, left->keys[left->num - 1]);
    193. } else if (node->childrens[idx+1]->num >= T->t) {
    194. btree_node *right = node->childrens[idx+1];
    195. node->keys[idx] = right->keys[0];
    196. btree_delete_key(T, right, right->keys[0]);
    197. } else {
    198. btree_merge(T, node, idx);
    199. btree_delete_key(T, node->childrens[idx], key);
    200. }
    201. } else {
    202. btree_node *child = node->childrens[idx];
    203. if (child == NULL) {
    204. printf("Cannot del key = %d\n", key);
    205. return ;
    206. }
    207. if (child->num == T->t - 1) {
    208. btree_node *left = NULL;
    209. btree_node *right = NULL;
    210. if (idx - 1 >= 0)
    211. left = node->childrens[idx-1];
    212. if (idx + 1 <= node->num)
    213. right = node->childrens[idx+1];
    214. if ((left && left->num >= T->t) ||
    215. (right && right->num >= T->t)) {
    216. int richR = 0;
    217. if (right) richR = 1;
    218. if (left && right) richR = (right->num > left->num) ? 1 : 0;
    219. if (right && right->num >= T->t && richR) { //borrow from next
    220. child->keys[child->num] = node->keys[idx];
    221. child->childrens[child->num+1] = right->childrens[0];
    222. child->num ++;
    223. node->keys[idx] = right->keys[0];
    224. for (i = 0;i < right->num - 1;i ++) {
    225. right->keys[i] = right->keys[i+1];
    226. right->childrens[i] = right->childrens[i+1];
    227. }
    228. right->keys[right->num-1] = 0;
    229. right->childrens[right->num-1] = right->childrens[right->num];
    230. right->childrens[right->num] = NULL;
    231. right->num --;
    232. } else { //borrow from prev
    233. for (i = child->num;i > 0;i --) {
    234. child->keys[i] = child->keys[i-1];
    235. child->childrens[i+1] = child->childrens[i];
    236. }
    237. child->childrens[1] = child->childrens[0];
    238. child->childrens[0] = left->childrens[left->num];
    239. child->keys[0] = node->keys[idx-1];
    240. child->num ++;
    241. left->keys[left->num-1] = 0;
    242. left->childrens[left->num] = NULL;
    243. left->num --;
    244. }
    245. } else if ((!left || (left->num == T->t - 1))
    246. && (!right || (right->num == T->t - 1))) {
    247. if (left && left->num == T->t - 1) {
    248. btree_merge(T, node, idx-1);
    249. child = left;
    250. } else if (right && right->num == T->t - 1) {
    251. btree_merge(T, node, idx);
    252. }
    253. }
    254. }
    255. btree_delete_key(T, child, key);
    256. }
    257. }
    258. int btree_delete(btree *T, KEY_VALUE key) {
    259. if (!T->root) return -1;
    260. btree_delete_key(T, T->root, key);
    261. return 0;
    262. }
    263. int main() {
    264. btree T = {0};
    265. btree_create(&T, 3);
    266. srand(48);
    267. int i = 0;
    268. char key[26] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    269. for (i = 0;i < 26;i ++) {
    270. //key[i] = rand() % 1000;
    271. printf("%c ", key[i]);
    272. btree_insert(&T, key[i]);
    273. }
    274. btree_print(&T, T.root, 0);
    275. for (i = 0;i < 26;i ++) {
    276. printf("\n---------------------------------\n");
    277. btree_delete(&T, key[25-i]);
    278. //btree_traverse(T.root);
    279. btree_print(&T, T.root, 0);
    280. }
    281. }