原文: https://www.programiz.com/dsa/deletion-from-a-b-tree

在本教程中,您将学习如何从 b 树中删除键。 此外,您还将找到在 C,C++ ,Java 和 Python 中从 B 树中删除键的工作示例。

删除 B 树上的元素包括三个主要事件:搜索要删除的键存在的节点,删除键并按需平衡树。

删除树时,可能会发生称为下溢的条件。 当节点包含的数量少于其应持有的最小键数时,就会发生下溢。

在研究删除操作之前,应了解以下术语:

  1. 有序前驱
    节点左子级上的最大键称为其有序前驱。
  2. 有序后继
    节点右子级上的最小键称为其有序后继。

删除操作

在执行以下步骤之前,必须了解有关度为m的 B 树的这些事实。

  1. 一个节点最多可以有m个子节点。 (即 3)
  2. 一个节点最多可以包含m - 1个键。 (即 2)
  3. 一个节点至少应具有⌈m/2⌉个子节点。 (即 2)
  4. 一个节点(根节点除外)应至少包含⌈m/2⌉ - 1键。 (即 1)

B 树中的删除操作主要有三种情况。

情况一

要删除的键位于叶子中。 有两种情况。

  1. 删除键不会违反节点应持有的最小键数的属性。
    在下面的树中,删除 32 不违反上述属性。
    从 B 树删除 - 图1
    从 B 树中删除叶子键(32)

  2. 键的删除违反了节点应持有的最小键数的属性。 在这种情况下,我们以从左到右的顺序从其直接相邻的兄弟节点借用键。
    首先,访问紧邻的左兄弟姐妹。 如果左兄弟节点的键数目超过最小数目,则从该节点借用键。
    否则,请检查以从紧邻的右同级节点借用。
    在下面的树中,删除 31 将导致上述情况。 让我们从左侧兄弟节点借用一个键。
    从 B 树删除 - 图2
    删除叶子键(31)
    如果两个直接同级节点都已经具有最小数量的键,则将该节点与左同级节点或右同级节点合并。 此合并是通过父节点完成的。
    在上述情况下,删除 30 个结果。
    从 B 树删除 - 图3
    删除叶子键(30)

情况二

如果要删除的键位于内部节点中,则会发生以下情况。

  1. 如果左子节点的键数超过最小数目,则删除的内部节点将替换为有序的前驱节点。
    从 B 树删除 - 图4
    删除内部节点(33)

  2. 如果正确的子项超过了最小数目的键,则删除的内部节点将被有序后继替换。

  3. 如果任一子项的键数恰好最小,则合并左子项和右子项。
    从 B 树删除 - 图5
    删除内部节点(30)
    合并后,如果父节点的键数少于最小数目,则像情况 I 一样查找同级。

情况三

在这种情况下,树的高度会缩小。 如果目标键位于内部节点中,并且键的删除导致节点中键的数量减少(即少于所需的最小数量),则寻找有序前驱和有序后继。 如果两个子级都包含最少数量的钥匙,则无法进行借用。 这导致情况二(3),即合并子级。

同样,寻找同胞借用钥匙。 但是,如果同级也只有最少数量的键,则将同级节点与父级合并。 相应地安排子级们(增加顺序)。

从 B 树删除 - 图6

删除内部节点(10)


Python,Java 和 C/C++ 示例

  1. # Deleting a key on a B-tree in Python
  2. # Btree node
  3. class BTreeNode:
  4. def __init__(self, leaf=False):
  5. self.leaf = leaf
  6. self.keys = []
  7. self.child = []
  8. class BTree:
  9. def __init__(self, t):
  10. self.root = BTreeNode(True)
  11. self.t = t
  12. # Insert a key
  13. def insert(self, k):
  14. root = self.root
  15. if len(root.keys) == (2 * self.t) - 1:
  16. temp = BTreeNode()
  17. self.root = temp
  18. temp.child.insert(0, root)
  19. self.split_child(temp, 0)
  20. self.insert_non_full(temp, k)
  21. else:
  22. self.insert_non_full(root, k)
  23. # Insert non full
  24. def insert_non_full(self, x, k):
  25. i = len(x.keys) - 1
  26. if x.leaf:
  27. x.keys.append((None, None))
  28. while i >= 0 and k[0] < x.keys[i][0]:
  29. x.keys[i + 1] = x.keys[i]
  30. i -= 1
  31. x.keys[i + 1] = k
  32. else:
  33. while i >= 0 and k[0] < x.keys[i][0]:
  34. i -= 1
  35. i += 1
  36. if len(x.child[i].keys) == (2 * self.t) - 1:
  37. self.split_child(x, i)
  38. if k[0] > x.keys[i][0]:
  39. i += 1
  40. self.insert_non_full(x.child[i], k)
  41. # Split the child
  42. def split_child(self, x, i):
  43. t = self.t
  44. y = x.child[i]
  45. z = BTreeNode(y.leaf)
  46. x.child.insert(i + 1, z)
  47. x.keys.insert(i, y.keys[t - 1])
  48. z.keys = y.keys[t: (2 * t) - 1]
  49. y.keys = y.keys[0: t - 1]
  50. if not y.leaf:
  51. z.child = y.child[t: 2 * t]
  52. y.child = y.child[0: t - 1]
  53. # Delete a node
  54. def delete(self, x, k):
  55. t = self.t
  56. i = 0
  57. while i < len(x.keys) and k[0] > x.keys[i][0]:
  58. i += 1
  59. if x.leaf:
  60. if i < len(x.keys) and x.keys[i][0] == k[0]:
  61. x.keys.pop(i)
  62. return
  63. return
  64. if i < len(x.keys) and x.keys[i][0] == k[0]:
  65. return self.delete_internal_node(x, k, i)
  66. elif len(x.child[i].keys) >= t:
  67. self.delete(x.child[i], k)
  68. else:
  69. if i != 0 and i + 2 < len(x.child):
  70. if len(x.child[i - 1].keys) >= t:
  71. self.delete_sibling(x, i, i - 1)
  72. elif len(x.child[i + 1].keys) >= t:
  73. self.delete_sibling(x, i, i + 1)
  74. else:
  75. self.delete_merge(x, i, i + 1)
  76. elif i == 0:
  77. if len(x.child[i + 1].keys) >= t:
  78. self.delete_sibling(x, i, i + 1)
  79. else:
  80. self.delete_merge(x, i, i + 1)
  81. elif i + 1 == len(x.child):
  82. if len(x.child[i - 1].keys) >= t:
  83. self.delete_sibling(x, i, i - 1)
  84. else:
  85. self.delete_merge(x, i, i - 1)
  86. self.delete(x.child[i], k)
  87. # Delete internal node
  88. def delete_internal_node(self, x, k, i):
  89. t = self.t
  90. if x.leaf:
  91. if x.keys[i][0] == k[0]:
  92. x.keys.pop(i)
  93. return
  94. return
  95. if len(x.child[i].keys) >= t:
  96. x.keys[i] = self.delete_predecessor(x.child[i])
  97. return
  98. elif len(x.child[i + 1].keys) >= t:
  99. x.keys[i] = self.delete_successor(x.child[i + 1])
  100. return
  101. else:
  102. self.delete_merge(x, i, i + 1)
  103. self.delete_internal_node(x.child[i], k, self.t - 1)
  104. # Delete the predecessor
  105. def delete_predecessor(self, x):
  106. if x.leaf:
  107. return x.pop()
  108. n = len(x.keys) - 1
  109. if len(x.child[n].keys) >= self.t:
  110. self.delete_sibling(x, n + 1, n)
  111. else:
  112. self.delete_merge(x, n, n + 1)
  113. self.delete_predecessor(x.child[n])
  114. # Delete the successor
  115. def delete_successor(self, x):
  116. if x.leaf:
  117. return x.keys.pop(0)
  118. if len(x.child[1].keys) >= self.t:
  119. self.delete_sibling(x, 0, 1)
  120. else:
  121. self.delete_merge(x, 0, 1)
  122. self.delete_successor(x.child[0])
  123. # Delete resolution
  124. def delete_merge(self, x, i, j):
  125. cnode = x.child[i]
  126. if j > i:
  127. rsnode = x.child[j]
  128. cnode.keys.append(x.keys[i])
  129. for k in range(len(rsnode.keys)):
  130. cnode.keys.append(rsnode.keys[k])
  131. if len(rsnode.child) > 0:
  132. cnode.child.append(rsnode.child[k])
  133. if len(rsnode.child) > 0:
  134. cnode.child.append(rsnode.child.pop())
  135. new = cnode
  136. x.keys.pop(i)
  137. x.child.pop(j)
  138. else:
  139. lsnode = x.child[j]
  140. lsnode.keys.append(x.keys[j])
  141. for i in range(len(cnode.keys)):
  142. lsnode.keys.append(cnode.keys[i])
  143. if len(lsnode.child) > 0:
  144. lsnode.child.append(cnode.child[i])
  145. if len(lsnode.child) > 0:
  146. lsnode.child.append(cnode.child.pop())
  147. new = lsnode
  148. x.keys.pop(j)
  149. x.child.pop(i)
  150. if x == self.root and len(x.keys) == 0:
  151. self.root = new
  152. # Delete the sibling
  153. def delete_sibling(self, x, i, j):
  154. cnode = x.child[i]
  155. if i < j:
  156. rsnode = x.child[j]
  157. cnode.keys.append(x.keys[i])
  158. x.keys[i] = rsnode.keys[0]
  159. if len(rsnode.child) > 0:
  160. cnode.child.append(rsnode.child[0])
  161. rsnode.child.pop(0)
  162. rsnode.keys.pop(0)
  163. else:
  164. lsnode = x.child[j]
  165. cnode.keys.insert(0, x.keys[i - 1])
  166. x.keys[i - 1] = lsnode.keys.pop()
  167. if len(lsnode.child) > 0:
  168. cnode.child.insert(0, lsnode.child.pop())
  169. # Print the tree
  170. def print_tree(self, x, l=0):
  171. print("Level ", l, " ", len(x.keys), end=":")
  172. for i in x.keys:
  173. print(i, end=" ")
  174. print()
  175. l += 1
  176. if len(x.child) > 0:
  177. for i in x.child:
  178. self.print_tree(i, l)
  179. def main():
  180. B = BTree(3)
  181. for i in range(10):
  182. B.insert((i, 2 * i))
  183. B.print_tree(B.root)
  184. B.delete(B.root, (8,))
  185. print("\n")
  186. B.print_tree(B.root)
  1. // Inserting a key on a B-tree in Java
  2. import java.util.Stack;
  3. public class BTree {
  4. private int T;
  5. public class Node {
  6. int n;
  7. int key[] = new int[2 * T - 1];
  8. Node child[] = new Node[2 * T];
  9. boolean leaf = true;
  10. public int Find(int k) {
  11. for (int i = 0; i < this.n; i++) {
  12. if (this.key[i] == k) {
  13. return i;
  14. }
  15. }
  16. return -1;
  17. };
  18. }
  19. public BTree(int t) {
  20. T = t;
  21. root = new Node();
  22. root.n = 0;
  23. root.leaf = true;
  24. }
  25. private Node root;
  26. // Search the key
  27. private Node Search(Node x, int key) {
  28. int i = 0;
  29. if (x == null)
  30. return x;
  31. for (i = 0; i < x.n; i++) {
  32. if (key < x.key[i]) {
  33. break;
  34. }
  35. if (key == x.key[i]) {
  36. return x;
  37. }
  38. }
  39. if (x.leaf) {
  40. return null;
  41. } else {
  42. return Search(x.child[i], key);
  43. }
  44. }
  45. // Split function
  46. private void Split(Node x, int pos, Node y) {
  47. Node z = new Node();
  48. z.leaf = y.leaf;
  49. z.n = T - 1;
  50. for (int j = 0; j < T - 1; j++) {
  51. z.key[j] = y.key[j + T];
  52. }
  53. if (!y.leaf) {
  54. for (int j = 0; j < T; j++) {
  55. z.child[j] = y.child[j + T];
  56. }
  57. }
  58. y.n = T - 1;
  59. for (int j = x.n; j >= pos + 1; j--) {
  60. x.child[j + 1] = x.child[j];
  61. }
  62. x.child[pos + 1] = z;
  63. for (int j = x.n - 1; j >= pos; j--) {
  64. x.key[j + 1] = x.key[j];
  65. }
  66. x.key[pos] = y.key[T - 1];
  67. x.n = x.n + 1;
  68. }
  69. // Insert the key
  70. public void Insert(final int key) {
  71. Node r = root;
  72. if (r.n == 2 * T - 1) {
  73. Node s = new Node();
  74. root = s;
  75. s.leaf = false;
  76. s.n = 0;
  77. s.child[0] = r;
  78. Split(s, 0, r);
  79. _Insert(s, key);
  80. } else {
  81. _Insert(r, key);
  82. }
  83. }
  84. // Insert the node
  85. final private void _Insert(Node x, int k) {
  86. if (x.leaf) {
  87. int i = 0;
  88. for (i = x.n - 1; i >= 0 && k < x.key[i]; i--) {
  89. x.key[i + 1] = x.key[i];
  90. }
  91. x.key[i + 1] = k;
  92. x.n = x.n + 1;
  93. } else {
  94. int i = 0;
  95. for (i = x.n - 1; i >= 0 && k < x.key[i]; i--) {
  96. }
  97. ;
  98. i++;
  99. Node tmp = x.child[i];
  100. if (tmp.n == 2 * T - 1) {
  101. Split(x, i, tmp);
  102. if (k > x.key[i]) {
  103. i++;
  104. }
  105. }
  106. _Insert(x.child[i], k);
  107. }
  108. }
  109. public void Show() {
  110. Show(root);
  111. }
  112. private void Remove(Node x, int key) {
  113. int pos = x.Find(key);
  114. if (pos != -1) {
  115. if (x.leaf) {
  116. int i = 0;
  117. for (i = 0; i < x.n && x.key[i] != key; i++) {
  118. }
  119. ;
  120. for (; i < x.n; i++) {
  121. if (i != 2 * T - 2) {
  122. x.key[i] = x.key[i + 1];
  123. }
  124. }
  125. x.n--;
  126. return;
  127. }
  128. if (!x.leaf) {
  129. Node pred = x.child[pos];
  130. int predKey = 0;
  131. if (pred.n >= T) {
  132. for (;;) {
  133. if (pred.leaf) {
  134. System.out.println(pred.n);
  135. predKey = pred.key[pred.n - 1];
  136. break;
  137. } else {
  138. pred = pred.child[pred.n];
  139. }
  140. }
  141. Remove(pred, predKey);
  142. x.key[pos] = predKey;
  143. return;
  144. }
  145. Node nextNode = x.child[pos + 1];
  146. if (nextNode.n >= T) {
  147. int nextKey = nextNode.key[0];
  148. if (!nextNode.leaf) {
  149. nextNode = nextNode.child[0];
  150. for (;;) {
  151. if (nextNode.leaf) {
  152. nextKey = nextNode.key[nextNode.n - 1];
  153. break;
  154. } else {
  155. nextNode = nextNode.child[nextNode.n];
  156. }
  157. }
  158. }
  159. Remove(nextNode, nextKey);
  160. x.key[pos] = nextKey;
  161. return;
  162. }
  163. int temp = pred.n + 1;
  164. pred.key[pred.n++] = x.key[pos];
  165. for (int i = 0, j = pred.n; i < nextNode.n; i++) {
  166. pred.key[j++] = nextNode.key[i];
  167. pred.n++;
  168. }
  169. for (int i = 0; i < nextNode.n + 1; i++) {
  170. pred.child[temp++] = nextNode.child[i];
  171. }
  172. x.child[pos] = pred;
  173. for (int i = pos; i < x.n; i++) {
  174. if (i != 2 * T - 2) {
  175. x.key[i] = x.key[i + 1];
  176. }
  177. }
  178. for (int i = pos + 1; i < x.n + 1; i++) {
  179. if (i != 2 * T - 1) {
  180. x.child[i] = x.child[i + 1];
  181. }
  182. }
  183. x.n--;
  184. if (x.n == 0) {
  185. if (x == root) {
  186. root = x.child[0];
  187. }
  188. x = x.child[0];
  189. }
  190. Remove(pred, key);
  191. return;
  192. }
  193. } else {
  194. for (pos = 0; pos < x.n; pos++) {
  195. if (x.key[pos] > key) {
  196. break;
  197. }
  198. }
  199. Node tmp = x.child[pos];
  200. if (tmp.n >= T) {
  201. Remove(tmp, key);
  202. return;
  203. }
  204. if (true) {
  205. Node nb = null;
  206. int devider = -1;
  207. if (pos != x.n && x.child[pos + 1].n >= T) {
  208. devider = x.key[pos];
  209. nb = x.child[pos + 1];
  210. x.key[pos] = nb.key[0];
  211. tmp.key[tmp.n++] = devider;
  212. tmp.child[tmp.n] = nb.child[0];
  213. for (int i = 1; i < nb.n; i++) {
  214. nb.key[i - 1] = nb.key[i];
  215. }
  216. for (int i = 1; i <= nb.n; i++) {
  217. nb.child[i - 1] = nb.child[i];
  218. }
  219. nb.n--;
  220. Remove(tmp, key);
  221. return;
  222. } else if (pos != 0 && x.child[pos - 1].n >= T) {
  223. devider = x.key[pos - 1];
  224. nb = x.child[pos - 1];
  225. x.key[pos - 1] = nb.key[nb.n - 1];
  226. Node child = nb.child[nb.n];
  227. nb.n--;
  228. for (int i = tmp.n; i > 0; i--) {
  229. tmp.key[i] = tmp.key[i - 1];
  230. }
  231. tmp.key[0] = devider;
  232. for (int i = tmp.n + 1; i > 0; i--) {
  233. tmp.child[i] = tmp.child[i - 1];
  234. }
  235. tmp.child[0] = child;
  236. tmp.n++;
  237. Remove(tmp, key);
  238. return;
  239. } else {
  240. Node lt = null;
  241. Node rt = null;
  242. boolean last = false;
  243. if (pos != x.n) {
  244. devider = x.key[pos];
  245. lt = x.child[pos];
  246. rt = x.child[pos + 1];
  247. } else {
  248. devider = x.key[pos - 1];
  249. rt = x.child[pos];
  250. lt = x.child[pos - 1];
  251. last = true;
  252. pos--;
  253. }
  254. for (int i = pos; i < x.n - 1; i++) {
  255. x.key[i] = x.key[i + 1];
  256. }
  257. for (int i = pos + 1; i < x.n; i++) {
  258. x.child[i] = x.child[i + 1];
  259. }
  260. x.n--;
  261. lt.key[lt.n++] = devider;
  262. for (int i = 0, j = lt.n; i < rt.n + 1; i++, j++) {
  263. if (i < rt.n) {
  264. lt.key[j] = rt.key[i];
  265. }
  266. lt.child[j] = rt.child[i];
  267. }
  268. lt.n += rt.n;
  269. if (x.n == 0) {
  270. if (x == root) {
  271. root = x.child[0];
  272. }
  273. x = x.child[0];
  274. }
  275. Remove(lt, key);
  276. return;
  277. }
  278. }
  279. }
  280. }
  281. public void Remove(int key) {
  282. Node x = Search(root, key);
  283. if (x == null) {
  284. return;
  285. }
  286. Remove(root, key);
  287. }
  288. public void Task(int a, int b) {
  289. Stack<Integer> st = new Stack<>();
  290. FindKeys(a, b, root, st);
  291. while (st.isEmpty() == false) {
  292. this.Remove(root, st.pop());
  293. }
  294. }
  295. private void FindKeys(int a, int b, Node x, Stack<Integer> st) {
  296. int i = 0;
  297. for (i = 0; i < x.n && x.key[i] < b; i++) {
  298. if (x.key[i] > a) {
  299. st.push(x.key[i]);
  300. }
  301. }
  302. if (!x.leaf) {
  303. for (int j = 0; j < i + 1; j++) {
  304. FindKeys(a, b, x.child[j], st);
  305. }
  306. }
  307. }
  308. public boolean Contain(int k) {
  309. if (this.Search(root, k) != null) {
  310. return true;
  311. } else {
  312. return false;
  313. }
  314. }
  315. // Show the node
  316. private void Show(Node x) {
  317. assert (x == null);
  318. for (int i = 0; i < x.n; i++) {
  319. System.out.print(x.key[i] + " ");
  320. }
  321. if (!x.leaf) {
  322. for (int i = 0; i < x.n + 1; i++) {
  323. Show(x.child[i]);
  324. }
  325. }
  326. }
  327. public static void main(String[] args) {
  328. BTree b = new BTree(3);
  329. b.Insert(8);
  330. b.Insert(9);
  331. b.Insert(10);
  332. b.Insert(11);
  333. b.Insert(15);
  334. b.Insert(20);
  335. b.Insert(17);
  336. b.Show();
  337. b.Remove(10);
  338. System.out.println();
  339. b.Show();
  340. }
  341. }
// Deleting a key from a B-tree in C

#include <stdio.h>
#include <stdlib.h>

#define MAX 3
#define MIN 2

struct BTreeNode {
  int item[MAX + 1], count;
  struct BTreeNode *linker[MAX + 1];
};

struct BTreeNode *root;

// Node creation
struct BTreeNode *createNode(int item, struct BTreeNode *child) {
  struct BTreeNode *newNode;
  newNode = (struct BTreeNode *)malloc(sizeof(struct BTreeNode));
  newNode->item[1] = item;
  newNode->count = 1;
  newNode->linker[0] = root;
  newNode->linker[1] = child;
  return newNode;
}

// Add value to the node
void addValToNode(int item, int pos, struct BTreeNode *node,
          struct BTreeNode *child) {
  int j = node->count;
  while (j > pos) {
    node->item[j + 1] = node->item[j];
    node->linker[j + 1] = node->linker[j];
    j--;
  }
  node->item[j + 1] = item;
  node->linker[j + 1] = child;
  node->count++;
}

// Split the node
void splitNode(int item, int *pval, int pos, struct BTreeNode *node,
         struct BTreeNode *child, struct BTreeNode **newNode) {
  int median, j;

  if (pos > MIN)
    median = MIN + 1;
  else
    median = MIN;

  *newNode = (struct BTreeNode *)malloc(sizeof(struct BTreeNode));
  j = median + 1;
  while (j <= MAX) {
    (*newNode)->item[j - median] = node->item[j];
    (*newNode)->linker[j - median] = node->linker[j];
    j++;
  }
  node->count = median;
  (*newNode)->count = MAX - median;

  if (pos <= MIN) {
    addValToNode(item, pos, node, child);
  } else {
    addValToNode(item, pos - median, *newNode, child);
  }
  *pval = node->item[node->count];
  (*newNode)->linker[0] = node->linker[node->count];
  node->count--;
}

// Set the value in the node
int setValueInNode(int item, int *pval,
           struct BTreeNode *node, struct BTreeNode **child) {
  int pos;
  if (!node) {
    *pval = item;
    *child = NULL;
    return 1;
  }

  if (item < node->item[1]) {
    pos = 0;
  } else {
    for (pos = node->count;
       (item < node->item[pos] && pos > 1); pos--)
      ;
    if (item == node->item[pos]) {
      printf("Duplicates not allowed\n");
      return 0;
    }
  }
  if (setValueInNode(item, pval, node->linker[pos], child)) {
    if (node->count < MAX) {
      addValToNode(*pval, pos, node, *child);
    } else {
      splitNode(*pval, pval, pos, node, *child, child);
      return 1;
    }
  }
  return 0;
}

// Insertion operation
void insertion(int item) {
  int flag, i;
  struct BTreeNode *child;

  flag = setValueInNode(item, &i, root, &child);
  if (flag)
    root = createNode(i, child);
}

// Copy the successor
void copySuccessor(struct BTreeNode *myNode, int pos) {
  struct BTreeNode *dummy;
  dummy = myNode->linker[pos];

  for (; dummy->linker[0] != NULL;)
    dummy = dummy->linker[0];
  myNode->item[pos] = dummy->item[1];
}

// Remove the value
void removeVal(struct BTreeNode *myNode, int pos) {
  int i = pos + 1;
  while (i <= myNode->count) {
    myNode->item[i - 1] = myNode->item[i];
    myNode->linker[i - 1] = myNode->linker[i];
    i++;
  }
  myNode->count--;
}

// Do right shift
void rightShift(struct BTreeNode *myNode, int pos) {
  struct BTreeNode *x = myNode->linker[pos];
  int j = x->count;

  while (j > 0) {
    x->item[j + 1] = x->item[j];
    x->linker[j + 1] = x->linker[j];
  }
  x->item[1] = myNode->item[pos];
  x->linker[1] = x->linker[0];
  x->count++;

  x = myNode->linker[pos - 1];
  myNode->item[pos] = x->item[x->count];
  myNode->linker[pos] = x->linker[x->count];
  x->count--;
  return;
}

// Do left shift
void leftShift(struct BTreeNode *myNode, int pos) {
  int j = 1;
  struct BTreeNode *x = myNode->linker[pos - 1];

  x->count++;
  x->item[x->count] = myNode->item[pos];
  x->linker[x->count] = myNode->linker[pos]->linker[0];

  x = myNode->linker[pos];
  myNode->item[pos] = x->item[1];
  x->linker[0] = x->linker[1];
  x->count--;

  while (j <= x->count) {
    x->item[j] = x->item[j + 1];
    x->linker[j] = x->linker[j + 1];
    j++;
  }
  return;
}

// Merge the nodes
void mergeNodes(struct BTreeNode *myNode, int pos) {
  int j = 1;
  struct BTreeNode *x1 = myNode->linker[pos], *x2 = myNode->linker[pos - 1];

  x2->count++;
  x2->item[x2->count] = myNode->item[pos];
  x2->linker[x2->count] = myNode->linker[0];

  while (j <= x1->count) {
    x2->count++;
    x2->item[x2->count] = x1->item[j];
    x2->linker[x2->count] = x1->linker[j];
    j++;
  }

  j = pos;
  while (j < myNode->count) {
    myNode->item[j] = myNode->item[j + 1];
    myNode->linker[j] = myNode->linker[j + 1];
    j++;
  }
  myNode->count--;
  free(x1);
}

// Adjust the node
void adjustNode(struct BTreeNode *myNode, int pos) {
  if (!pos) {
    if (myNode->linker[1]->count > MIN) {
      leftShift(myNode, 1);
    } else {
      mergeNodes(myNode, 1);
    }
  } else {
    if (myNode->count != pos) {
      if (myNode->linker[pos - 1]->count > MIN) {
        rightShift(myNode, pos);
      } else {
        if (myNode->linker[pos + 1]->count > MIN) {
          leftShift(myNode, pos + 1);
        } else {
          mergeNodes(myNode, pos);
        }
      }
    } else {
      if (myNode->linker[pos - 1]->count > MIN)
        rightShift(myNode, pos);
      else
        mergeNodes(myNode, pos);
    }
  }
}

// Delete a value from the node
int delValFromNode(int item, struct BTreeNode *myNode) {
  int pos, flag = 0;
  if (myNode) {
    if (item < myNode->item[1]) {
      pos = 0;
      flag = 0;
    } else {
      for (pos = myNode->count; (item < myNode->item[pos] && pos > 1); pos--)
        ;
      if (item == myNode->item[pos]) {
        flag = 1;
      } else {
        flag = 0;
      }
    }
    if (flag) {
      if (myNode->linker[pos - 1]) {
        copySuccessor(myNode, pos);
        flag = delValFromNode(myNode->item[pos], myNode->linker[pos]);
        if (flag == 0) {
          printf("Given data is not present in B-Tree\n");
        }
      } else {
        removeVal(myNode, pos);
      }
    } else {
      flag = delValFromNode(item, myNode->linker[pos]);
    }
    if (myNode->linker[pos]) {
      if (myNode->linker[pos]->count < MIN)
        adjustNode(myNode, pos);
    }
  }
  return flag;
}

// Delete operaiton
void delete (int item, struct BTreeNode *myNode) {
  struct BTreeNode *tmp;
  if (!delValFromNode(item, myNode)) {
    printf("Not present\n");
    return;
  } else {
    if (myNode->count == 0) {
      tmp = myNode;
      myNode = myNode->linker[0];
      free(tmp);
    }
  }
  root = myNode;
  return;
}

void searching(int item, int *pos, struct BTreeNode *myNode) {
  if (!myNode) {
    return;
  }

  if (item < myNode->item[1]) {
    *pos = 0;
  } else {
    for (*pos = myNode->count;
       (item < myNode->item[*pos] && *pos > 1); (*pos)--)
      ;
    if (item == myNode->item[*pos]) {
      printf("%d present in B-tree", item);
      return;
    }
  }
  searching(item, pos, myNode->linker[*pos]);
  return;
}

void traversal(struct BTreeNode *myNode) {
  int i;
  if (myNode) {
    for (i = 0; i < myNode->count; i++) {
      traversal(myNode->linker[i]);
      printf("%d ", myNode->item[i + 1]);
    }
    traversal(myNode->linker[i]);
  }
}

int main() {
  int item, ch;

  insertion(8);
  insertion(9);
  insertion(10);
  insertion(11);
  insertion(15);
  insertion(16);
  insertion(17);
  insertion(18);
  insertion(20);
  insertion(23);

  traversal(root);

  delete (20, root);
  printf("\n");
  traversal(root);
}
// Deleting a key from a B-tree in C++

#include <iostream>
using namespace std;

class BTreeNode {
  int *keys;
  int t;
  BTreeNode **C;
  int n;
  bool leaf;

   public:
  BTreeNode(int _t, bool _leaf);

  void traverse();

  int findKey(int k);
  void insertNonFull(int k);
  void splitChild(int i, BTreeNode *y);
  void deletion(int k);
  void removeFromLeaf(int idx);
  void removeFromNonLeaf(int idx);
  int getPredecessor(int idx);
  int getSuccessor(int idx);
  void fill(int idx);
  void borrowFromPrev(int idx);
  void borrowFromNext(int idx);
  void merge(int idx);
  friend class BTree;
};

class BTree {
  BTreeNode *root;
  int t;

   public:
  BTree(int _t) {
    root = NULL;
    t = _t;
  }

  void traverse() {
    if (root != NULL)
      root->traverse();
  }

  void insertion(int k);

  void deletion(int k);
};

// B tree node
BTreeNode::BTreeNode(int t1, bool leaf1) {
  t = t1;
  leaf = leaf1;

  keys = new int[2 * t - 1];
  C = new BTreeNode *[2 * t];

  n = 0;
}

// Find the key
int BTreeNode::findKey(int k) {
  int idx = 0;
  while (idx < n && keys[idx] < k)
    ++idx;
  return idx;
}

// Deletion operation
void BTreeNode::deletion(int k) {
  int idx = findKey(k);

  if (idx < n && keys[idx] == k) {
    if (leaf)
      removeFromLeaf(idx);
    else
      removeFromNonLeaf(idx);
  } else {
    if (leaf) {
      cout << "The key " << k << " is does not exist in the tree\n";
      return;
    }

    bool flag = ((idx == n) ? true : false);

    if (C[idx]->n < t)
      fill(idx);

    if (flag && idx > n)
      C[idx - 1]->deletion(k);
    else
      C[idx]->deletion(k);
  }
  return;
}

// Remove from the leaf
void BTreeNode::removeFromLeaf(int idx) {
  for (int i = idx + 1; i < n; ++i)
    keys[i - 1] = keys[i];

  n--;

  return;
}

// Delete from non leaf node
void BTreeNode::removeFromNonLeaf(int idx) {
  int k = keys[idx];

  if (C[idx]->n >= t) {
    int pred = getPredecessor(idx);
    keys[idx] = pred;
    C[idx]->deletion(pred);
  }

  else if (C[idx + 1]->n >= t) {
    int succ = getSuccessor(idx);
    keys[idx] = succ;
    C[idx + 1]->deletion(succ);
  }

  else {
    merge(idx);
    C[idx]->deletion(k);
  }
  return;
}

int BTreeNode::getPredecessor(int idx) {
  BTreeNode *cur = C[idx];
  while (!cur->leaf)
    cur = cur->C[cur->n];

  return cur->keys[cur->n - 1];
}

int BTreeNode::getSuccessor(int idx) {
  BTreeNode *cur = C[idx + 1];
  while (!cur->leaf)
    cur = cur->C[0];

  return cur->keys[0];
}

void BTreeNode::fill(int idx) {
  if (idx != 0 && C[idx - 1]->n >= t)
    borrowFromPrev(idx);

  else if (idx != n && C[idx + 1]->n >= t)
    borrowFromNext(idx);

  else {
    if (idx != n)
      merge(idx);
    else
      merge(idx - 1);
  }
  return;
}

// Borrow from previous
void BTreeNode::borrowFromPrev(int idx) {
  BTreeNode *child = C[idx];
  BTreeNode *sibling = C[idx - 1];

  for (int i = child->n - 1; i >= 0; --i)
    child->keys[i + 1] = child->keys[i];

  if (!child->leaf) {
    for (int i = child->n; i >= 0; --i)
      child->C[i + 1] = child->C[i];
  }

  child->keys[0] = keys[idx - 1];

  if (!child->leaf)
    child->C[0] = sibling->C[sibling->n];

  keys[idx - 1] = sibling->keys[sibling->n - 1];

  child->n += 1;
  sibling->n -= 1;

  return;
}

// Borrow from the next
void BTreeNode::borrowFromNext(int idx) {
  BTreeNode *child = C[idx];
  BTreeNode *sibling = C[idx + 1];

  child->keys[(child->n)] = keys[idx];

  if (!(child->leaf))
    child->C[(child->n) + 1] = sibling->C[0];

  keys[idx] = sibling->keys[0];

  for (int i = 1; i < sibling->n; ++i)
    sibling->keys[i - 1] = sibling->keys[i];

  if (!sibling->leaf) {
    for (int i = 1; i <= sibling->n; ++i)
      sibling->C[i - 1] = sibling->C[i];
  }

  child->n += 1;
  sibling->n -= 1;

  return;
}

// Merge
void BTreeNode::merge(int idx) {
  BTreeNode *child = C[idx];
  BTreeNode *sibling = C[idx + 1];

  child->keys[t - 1] = keys[idx];

  for (int i = 0; i < sibling->n; ++i)
    child->keys[i + t] = sibling->keys[i];

  if (!child->leaf) {
    for (int i = 0; i <= sibling->n; ++i)
      child->C[i + t] = sibling->C[i];
  }

  for (int i = idx + 1; i < n; ++i)
    keys[i - 1] = keys[i];

  for (int i = idx + 2; i <= n; ++i)
    C[i - 1] = C[i];

  child->n += sibling->n + 1;
  n--;

  delete (sibling);
  return;
}

// Insertion operation
void BTree::insertion(int k) {
  if (root == NULL) {
    root = new BTreeNode(t, true);
    root->keys[0] = k;
    root->n = 1;
  } else {
    if (root->n == 2 * t - 1) {
      BTreeNode *s = new BTreeNode(t, false);

      s->C[0] = root;

      s->splitChild(0, root);

      int i = 0;
      if (s->keys[0] < k)
        i++;
      s->C[i]->insertNonFull(k);

      root = s;
    } else
      root->insertNonFull(k);
  }
}

// Insertion non full
void BTreeNode::insertNonFull(int k) {
  int i = n - 1;

  if (leaf == true) {
    while (i >= 0 && keys[i] > k) {
      keys[i + 1] = keys[i];
      i--;
    }

    keys[i + 1] = k;
    n = n + 1;
  } else {
    while (i >= 0 && keys[i] > k)
      i--;

    if (C[i + 1]->n == 2 * t - 1) {
      splitChild(i + 1, C[i + 1]);

      if (keys[i + 1] < k)
        i++;
    }
    C[i + 1]->insertNonFull(k);
  }
}

// Split child
void BTreeNode::splitChild(int i, BTreeNode *y) {
  BTreeNode *z = new BTreeNode(y->t, y->leaf);
  z->n = t - 1;

  for (int j = 0; j < t - 1; j++)
    z->keys[j] = y->keys[j + t];

  if (y->leaf == false) {
    for (int j = 0; j < t; j++)
      z->C[j] = y->C[j + t];
  }

  y->n = t - 1;

  for (int j = n; j >= i + 1; j--)
    C[j + 1] = C[j];

  C[i + 1] = z;

  for (int j = n - 1; j >= i; j--)
    keys[j + 1] = keys[j];

  keys[i] = y->keys[t - 1];

  n = n + 1;
}

// Traverse
void BTreeNode::traverse() {
  int i;
  for (i = 0; i < n; i++) {
    if (leaf == false)
      C[i]->traverse();
    cout << " " << keys[i];
  }

  if (leaf == false)
    C[i]->traverse();
}

// Delete Operation
void BTree::deletion(int k) {
  if (!root) {
    cout << "The tree is empty\n";
    return;
  }

  root->deletion(k);

  if (root->n == 0) {
    BTreeNode *tmp = root;
    if (root->leaf)
      root = NULL;
    else
      root = root->C[0];

    delete tmp;
  }
  return;
}

int main() {
  BTree t(3);
  t.insertion(8);
  t.insertion(9);
  t.insertion(10);
  t.insertion(11);
  t.insertion(15);
  t.insertion(16);
  t.insertion(17);
  t.insertion(18);
  t.insertion(20);
  t.insertion(23);

  cout << "The B-tree is: ";
  t.traverse();

  t.deletion(20);

  cout << "\nThe B-tree is: ";
  t.traverse();
}

删除复杂度

最佳情况时间复杂度:Θ(log n)

平均情况空间复杂度:Θ(n)

最坏情况的空间复杂度:Θ(n)