📅  最后修改于: 2023-12-03 15:10:19.509000             🧑  作者: Mango
当我们需要在海量数据中进行高效的查找和排序时,B树和B+树是一种很好的选择。这两种树结构都是一种平衡树,可以在平均时间复杂度为 O(log n) 的情况下进行搜索、插入和删除。
B树是一种自适应数据结构,它可以适应不同大小的页(如硬盘、内存),并且可以在日志文件、数据库索引和操作系统文件系统等场景中广泛应用。B+树是在B树的基础上进行改进,它更适合用于高效地执行范围查询操作。
从B树或B+树中删除一个元素需要执行以下步骤:
以下是B树删除一个元素的Python代码示例:
class BNode:
def __init__(self, leaf=False):
self.keys = []
self.child = []
self.leaf = leaf
def find(self, k):
i = 0
while i < len(self.keys) and k > self.keys[i][0]:
i += 1
if i < len(self.keys) and k == self.keys[i][0]:
return self.keys[i][1]
elif self.leaf:
return None
else:
return self.child[i].find(k)
def insert(self, k, v):
i = 0
while i < len(self.keys) and k > self.keys[i][0]:
i += 1
if i < len(self.keys) and k == self.keys[i][0]:
self.keys[i] = (k, v)
elif self.leaf:
self.keys.insert(i, (k, v))
else:
if len(self.child[i].keys) == 2 * t - 1:
self.split_child(i)
if k > self.keys[i][0]:
i += 1
self.child[i].insert(k, v)
def split_child(self, i):
t = BNode.t
x = self.child[i]
y = BNode(leaf=x.leaf)
self.child.insert(i + 1, y)
self.keys.insert(i, x.keys[t - 1])
y.keys = x.keys[t:]
x.keys = x.keys[:t - 1]
y.child = x.child[t:]
x.child = x.child[:t - 1]
def __str__(self):
return ('Leaf ' if self.leaf else 'Internal ') + \
''.join(str(self.keys[i]) for i in range(len(self.keys))) + \
' ' + ','.join(str(self.child[i].keys[0][0]) for i in range(len(self.child)))
@classmethod
def set_order(cls, t):
cls.t = t
class BTree:
def __init__(self, t):
BNode.set_order(t)
self.root = BNode(leaf=True)
def __getitem__(self, k):
return self.root.find(k)
def insert(self, k, v):
if len(self.root.keys) == 2 * BNode.t - 1:
new_root = BNode()
new_root.child.append(self.root)
new_root.split_child(0)
self.root = new_root
self.root.insert(k, v)
def __str__(self):
return str(self.root)
def find_min(self, node):
if not node:
return None
elif node.leaf:
return node.keys[0][0]
else:
return self.find_min(node.child[0])
def delete(self, k):
return self._delete(self.root, k)
def _delete(self, node, k):
t = BNode.t
i = 0
while i < len(node.keys) and k > node.keys[i][0]:
i += 1
if node.leaf:
if i < len(node.keys) and node.keys[i][0] == k:
node.keys.pop(i)
return True
else:
return False
elif i < len(node.keys) and node.keys[i][0] == k:
if len(node.child[i].keys) >= t:
node.keys[i] = (node.child[i].keys[-1][0], node.child[i].keys[-1][1])
self._delete(node.child[i], node.child[i].keys[-1][0])
elif len(node.child[i + 1].keys) >= t:
node.keys[i] = (node.child[i + 1].keys[0][0], node.child[i + 1].keys[0][1])
self._delete(node.child[i + 1], node.child[i + 1].keys[0][0])
else:
node.child[i].keys.append(node.keys[i])
node.child[i].keys += node.child[i + 1].keys
node.child[i].child += node.child[i + 1].child
node.child.pop(i + 1)
node.keys.pop(i)
if len(node.keys) == 0:
self.root = node.child[0]
return True
else:
if len(node.child[i].keys) == t - 1:
if i != 0 and len(node.child[i - 1].keys) >= t:
node.child[i].keys.insert(0, node.keys[i - 1])
node.child[i].child.insert(0, node.child[i - 1].child.pop())
node.keys[i - 1] = node.child[i - 1].keys.pop()
elif i != len(node.keys) and len(node.child[i + 1].keys) >= t:
node.child[i].keys.append(node.keys[i])
node.child[i].child.append(node.child[i + 1].child.pop(0))
node.keys[i] = node.child[i + 1].keys.pop(0)
elif i != 0:
node.child[i - 1].keys.append(node.keys[i - 1])
node.child[i - 1].keys += node.child[i].keys
node.child[i - 1].child += node.child[i].child
node.child.pop(i)
node.keys.pop(i - 1)
else:
node.child[0].keys += node.child[1].keys
node.child[0].child += node.child[1].child
node.child.pop(1)
node.keys.pop(0)
return self._delete(node.child[i], k)
else:
return self._delete(node.child[i], k)
以上是B树删除一个元素的Python代码示例,可以通过执行以下代码实现删除操作:
t = 3
bt = BTree(t)
for i in range(10):
bt.insert('k' + str(i), i)
print(bt)
bt.delete('k5')
print(bt)
下面是B+树删除一个元素的Python代码示例:
class BPlusTreeNode:
def __init__(self, leaf=False):
# m叉树
self.key = []
self.child = []
# 是否为叶子节点
self.leaf = leaf
self.next = None
@classmethod
def set_order(cls, m):
cls.m = m
def is_full(self):
return len(self.key) == BPlusTreeNode.m - 1
def split(self, parent, at_idx):
assert self.is_full()
new_node = type(self)()
mid_idx = BPlusTreeNode.m // 2 - 1
mid_key, self.key[mid_idx] = self.key[mid_idx], None
new_node.key = self.key[mid_idx + 1:]
self.key = self.key[:mid_idx]
if not self.leaf:
new_node.child = self.child[mid_idx + 1:]
self.child = self.child[:mid_idx + 1]
new_node.next = self.next
self.next = new_node
parent.insert_child(mid_key, self, new_node, at_idx)
def insert_child(self, key, left, right, at_idx):
self.key.insert(at_idx, key)
self.child.insert(at_idx, left)
self.child[at_idx + 1] = right
def remove_child(self, at_idx):
self.key.pop(at_idx)
self.child.pop(at_idx + 1)
class BPlusTree:
def __init__(self, m):
BPlusTreeNode.set_order(m)
self.root = BPlusTreeNode(leaf=True)
def search(self, key):
node = self.root
while not node.leaf:
idx = node.key.index(key) if key in node.key else node.find_idx(key)
node = node.child[idx]
assert node is None or key in node.key
return node
def insert(self, key):
node = self.root
if node.is_full():
new_root = BPlusTreeNode()
self.root = new_root
node.split(new_root, 0)
self._insert(new_root, key)
else:
self._insert(node, key)
def _insert(self, node, key):
insert_idx = node.find_idx(key)
if node.leaf:
node.key.insert(insert_idx, key)
else:
child = node.child[insert_idx]
if child.is_full():
node.split(node, insert_idx)
if key > node.key[insert_idx]:
insert_idx += 1
child = node.child[insert_idx]
self._insert(child, key)
def delete(self, key):
node = self.search(key)
if node:
assert key in node.key
delete_idx = node.key.index(key)
node.key.pop(delete_idx)
if node.is_empty():
if node is self.root:
self.root = None
else:
node.parent.remove_child(node.index)
if node.next and not node.next.is_minimal():
node.key.append(node.next.key.pop(0))
if not node.leaf:
node.child.append(node.next.child.pop(0))
node.join()
def __repr__(self):
keys = []
def traverse(node):
if node:
if node.leaf:
keys.extend(node.key)
else:
for i in range(len(node.key)):
traverse(node.child[i])
keys.append(node.key[i])
traverse(node.child[-1])
traverse(self.root)
return repr(keys)
bt = BPlusTree(4)
for i in range(20):
bt.insert(i)
print(bt)
bt.delete(7)
print(bt)
以上是B+树删除一个元素的Python代码示例,可以通过执行以下代码实现删除操作:
bt = BPlusTree(4)
for i in range(20):
bt.insert(i)
print(bt)
bt.delete(7)
print(bt)
使用B树或B+树进行高效的查找和排序是很好的选择,但是在实现中需要注意的细节也很多,需要仔细地考虑各种情况。在实际场景中,我们需要根据数据的特点来选择合适的度数和节点大小,以确保整个树结构的效率和可靠性。