跳到主要内容

向B树中插入

提示
  1. B树插入概述:在B树中插入元素涉及两个主要步骤:首先是搜索合适的节点进行插入,其次是在必要时分裂节点。插入操作总是从底部开始,自底向上进行。
  2. 插入过程:若树为空,则创建一个根节点并插入关键字;若节点已满,则在中间位置进行分裂,并将中间关键字向上推,左右关键字分别成为左右子节点;若节点未满,直接按升序插入关键字。
  3. 插入示例:例如,插入关键字8、9、10、11、15、20和17到B树中,会经历不同的插入和节点分裂步骤,最终形成一个结构化的B树。

在B树上插入元素包括两个事件:搜索适当的节点以插入元素和分裂节点(如果需要)。插入操作总是以自底向上的方式进行。

让我们在下面了解这些事件。

插入操作

  1. 如果树为空,则分配一个根节点并插入关键字。
  2. 更新节点中允许的关键字数。
  3. 搜索适当的节点以进行插入。
  4. 如果节点已满,请按以下步骤操作。
  5. 按升序插入元素。
  6. 现在,有超过其限制的元素。因此,在中间位置进行分裂。
  7. 将中间关键字向上推并将左侧的关键字作为左子节点,右侧的关键字作为右子节点。
  8. 如果节点未满,请按以下步骤操作。
  9. 按升序插入节点。

插入示例

让我们通过下面的插入操作示例来了解。

要插入的元素是 8、9、10、11、15、20 和 17。

将元素插入B树

插入元素的算法

BreeInsertion(T, k)
r root[T]
if n[r] = 2t - 1
s = AllocateNode()
root[T] = s
leaf[s] = FALSE
n[s] <- 0
c1[s] <- r
BtreeSplitChild(s, 1, r)
BtreeInsertNonFull(s, k)
else BtreeInsertNonFull(r, k)
BtreeInsertNonFull(x, k)
i = n[x]
if leaf[x]
while i ≥ 1 and k < keyi[x]
keyi+1 [x] = keyi[x]
i = i - 1
keyi+1[x] = k
n[x] = n[x] + 1
else while i ≥ 1 and k < keyi[x]
i = i - 1
i = i + 1
if n[ci[x]] == 2t - 1
BtreeSplitChild(x, i, ci[x])
if k &rt; keyi[x]
i = i + 1
BtreeInsertNonFull(ci[x], k)
BtreeSplitChild(x, i)
BtreeSplitChild(x, i, y)
z = AllocateNode()
leaf[z] = leaf[y]
n[z] = t - 1
for j = 1 to t - 1
keyj[z] = keyj+t[y]
if not leaf [y]
for j = 1 to t
cj[z] = cj + t[y]
n[y] = t - 1
for j = n[x] + 1 to i + 1
cj+1[x] = cj[x]
ci+1[x] = z
for j = n[x] to i
keyj+1[x] = keyj[x]
keyi[x] = keyt[y]
n[x] = n[x] + 1

Python、Java 和 C/C++ 示例

Python Java C C++

# 在Python中插入B树上的关键字


# 创建一个节点
class BTreeNode:
def __init__(self, leaf=False):
self.leaf = leaf
self.keys = []
self.child = []


# 树
class BTree:
def __init__(self, t):
self.root = BTreeNode(True)
self.t = t

# 插入节点
def insert(self, k):
root = self.root
if len(root.keys) == (2 * self.t) - 1:
temp = BTreeNode()
self.root = temp
temp.child.insert(0, root)
self.split_child(temp, 0)
self.insert_non_full(temp, k)
else:
self.insert_non_full(root, k)

# 插入非满的节点
def insert_non_full(self, x, k):
i = len(x.keys) - 1
if x.leaf:
x.keys.append((None, None))
while i >= 0 and k[0] < x.keys[i][0]:
x.keys[i + 1] = x.keys[i]
i -= 1
x.keys[i + 1] = k
else:
while i >= 0 and k[0] < x.keys[i][0]:
i -= 1
i += 1
if len(x.child[i].keys) == (2 * self.t) - 1:
self.split_child(x, i)
if k[0] > x.keys[i][0]:
i += 1
self.insert_non_full(x.child[i], k)

# 分裂子节点
def split_child(self, x, i):
t = self.t
y = x.child[i]
z = BTreeNode(y.leaf)
x.child.insert(i + 1, z)
x.keys.insert(i, y.keys[t - 1])
z.keys = y.keys[t: (2 * t) - 1]
y.keys = y.keys[0: t - 1]
if not y.leaf:
z.child = y.child[t: 2 * t]
y.child = y.child[0: t - 1]

# 打印树
def print_tree(self, x, l=0):
print("Level ", l, " ", len(x.keys), end=":")
for i in x.keys:
print(i, end=" ")
print()
l += 1
if len(x.child) > 0:
for i in x.child:
self.print_tree(i, l)


def main():
B = BTree(3)

for i in range(10):
B.insert((i, 2 * i))

B.print_tree(B.root)


if __name__ == '__main__':
main()
// 在Java中插入B树上的关键字

public class BTree {

private int T;

// 节点创建
public class Node {
int n;
int key[] = new int[2 * T - 1];
Node child[] = new Node[2 * T];
boolean leaf = true;

public int Find(int k) {
for (int i = 0; i < this.n; i++) {
if (this.key[i] == k) {
return i;
}
}
return -1;
};
}

public BTree(int t) {
T = t;
root = new Node();
root.n = 0;
root.leaf = true;
}

private Node root;

// 分裂
private void split(Node x, int pos, Node y) {
Node z = new Node();
z.leaf = y.leaf;
z.n = T - 1;
for (int j = 0; j < T - 1; j++) {
z.key[j] = y.key[j + T];
}
if (!y.leaf) {
for (int j = 0; j < T; j++) {
z.child[j] = y.child[j + T];
}
}
y.n = T - 1;
for (int j = x.n; j >= pos + 1; j--) {
x.child[j + 1] = x.child[j];
}
x.child[pos + 1] = z;

for (int j = x.n - 1; j >= pos; j--) {
x.key[j + 1] = x.key[j];
}
x.key[pos] = y.key[T - 1];
x.n = x.n + 1;
}

// 插入关键字
public void insert(final int key) {
Node r = root;
if (r.n == 2 * T - 1) {
Node s = new Node();
root = s;
s.leaf = false;
s.n = 0;
s.child[0] = r;
split(s, 0, r);
_insert(s, key);
} else {
_insert(r, key);
}
}

// 插入节点
final private void _insert(Node x, int k) {

if (x.leaf) {
int i = 0;
for (i = x.n - 1; i >= 0 && k < x.key[i]; i--) {
x.key[i + 1] = x.key[i];
}
x.key[i + 1] = k;
x.n = x.n + 1;
} else {
int i = 0;
for (i = x.n - 1; i >= 0 && k < x.key[i]; i--) {
}
;
i++;
Node tmp = x.child[i];
if (tmp.n == 2 * T - 1) {
split(x, i, tmp);
if (k > x.key[i]) {
i++;
}
}
_insert(x.child[i], k);
}

}

public void display() {
display(root);
}

// 显示树
private void display(Node x) {
assert (x == null);
for (int i = 0; i < x.n; i++) {
System.out.print(x.key[i] + " ");
}
if (!x.leaf) {
for (int i = 0; i < x.n + 1; i++) {
display(x.child[i]);
}
}
}

public static void main(String[] args) {
BTree b = new BTree(3);
b.insert(8);
b.insert(9);
b.insert(10);
b.insert(11);
b.insert(15);
b.insert(20);
b.insert(17);

b.display();
}
}

这是一个在Java中实现B树关键字插入的示例。 B树是一种自平衡的数据结构,用于高效地存储和检索数据。上面的代码演示了如何创建B树、插入关键字以及显示B树的内容。 // 在 C 中插入键到 B 树

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

#define MAX 3
#define MIN 2

struct btreeNode {
int item[MAX + 1], count;
struct btreeNode *link[MAX + 1];
};

struct btreeNode *root;

// 创建节点
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->link[0] = root;
newNode->link[1] = child;
return newNode;
}

// 插入值
void insertValue(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->link[j + 1] = node->link[j];
j--;
}
node->item[j + 1] = item;
node->link[j + 1] = child;
node->count++;
}

// 分裂节点
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)->link[j - median] = node->link[j];
j++;
}
node->count = median;
(*newNode)->count = MAX - median;

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

// 设置节点值
int setNodeValue(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 (setNodeValue(item, pval, node->link[pos], child)) {
if (node->count < MAX) {
insertValue(*pval, pos, node, *child);
} else {
splitNode(*pval, pval, pos, node, *child, child);
return 1;
}
}
return 0;
}

// 插入值
void insertion(int item) {
int flag, i;
struct btreeNode *child;

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

// 复制后继者
void copySuccessor(struct btreeNode *myNode, int pos) {
struct btreeNode *dummy;
dummy = myNode->link[pos];

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

// 右移
void rightShift(struct btreeNode *myNode, int pos) {
struct btreeNode *x = myNode->link[pos];
int j = x->count;

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

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

// 左移
void leftShift(struct btreeNode *myNode, int pos) {
int j = 1;
struct btreeNode *x = myNode->link[pos - 1];

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

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

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

// 合并节点
void mergeNodes(struct btreeNode *myNode, int pos) {
int j = 1;
struct btreeNode *x1 = myNode->link[pos], *x2 = myNode->link[pos - 1];

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

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

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

// 调整节点
void adjustNode(struct btreeNode *myNode, int pos) {
if (!pos) {
if (myNode->link[1]->count > MIN) {
leftShift(myNode, 1);
} else {
mergeNodes(myNode, 1);
}
} else {
if (myNode->count != pos) {
if (myNode->link[pos - 1]->count > MIN) {
rightShift(myNode, pos);
} else {
if (myNode->link[pos + 1]->count > MIN) {
leftShift(myNode, pos + 1);
} else {
mergeNodes(myNode, pos);
}
}
} else {
if (myNode->link[pos - 1]->count > MIN)
rightShift(myNode, pos);
else
mergeNodes(myNode, pos);
}
}
}

// Traverse the tree
void traversal(struct btreeNode *myNode) {
int i;
if (myNode) {
for (i = 0; i < myNode->count; i++) {
traversal(myNode->link[i]);
printf("%d ", myNode->item[i + 1]);
}
traversal(myNode->link[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);
}
// 在C++中插入B树上的关键字

#include <iostream>
using namespace std;

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

public:
Node(int _t, bool _leaf);

void insertNonFull(int k);
void splitChild(int i, Node *y);
void traverse();

friend class BTree;
};

class BTree {
Node *root;
int t;

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

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

void insert(int k);
};

Node::Node(int t1, bool leaf1) {
t = t1;
leaf = leaf1;

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

n = 0;
}

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

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

// 插入节点
void BTree::insert(int k) {
if (root == NULL) {
root = new Node(t, true);
root->keys[0] = k;
root->n = 1;
} else {
if (root->n == 2 * t - 1) {
Node *s = new Node(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);
}
}

// 插入非满条件
void Node::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);
}
}

// 分裂子节点
void Node::splitChild(int i, Node *y) {
Node *z = new Node(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;
}

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

cout << "B树是:";
t.traverse();
}