使用python实现BTree
import uuid
import random
import time
class BTree:
"""
BT实现
最大子树个数:5,插入【1~27示意图】
第1步: 插入1
节点: 1
子节点 None
...
第5步: 插入5
节点: 1,2,3,4,5
子节点: None
---> 节点数 = 5,节点分裂
节点: 3
子节点: [1,2][4,5]
第6步: 插入6
节点: 3
子节点: [1,2][4,5,6]
...
第8步: 插入8
节点: 3
子节点: [1,2][4,5,6,7,8]
---> 有节点数 = 5,节点分裂,[4,5,6,7,8] 分裂成[4,5][7,8]和6,6上升到父节点中
节点: 3, 6
子节点: [1,2][4,5][7,8]
...
第11步: 插入11
节点: 3, 6
子节点: [1,2][4,5][7,8,9,10,11]
---> 有节点数 = 5,节点分裂,[7,8,9,10,11] 分裂成[7,8][10,11]和9,9上升到父节点中
节点: 3, 6, 9
子节点: [1,2][4,5][7,8][10,11]
...
第16步: 插入16
节点: 3, 6, 9, 12
子节点: [1,2][4,5][7,8][10,11][13,14,15,16]
第17步: 插入17
节点: 3, 6, 9, 12
子节点: [1,2][4,5][7,8][10,11][13,14,15,16,17]
---> 有节点数 = 5,节点分裂,[13,14,15,16,17] 分裂成[13,14][16,17]和15,15上升到父节点中
节点: 3, 6, 9, 12, 15
子节点: [1,2][4,5][7,8][10,11][13,14][16,17]
---> 有节点数 = 5,节点分裂,[3, 6, 9, 12, 15] 分裂成[3, 6][12, 15]和9,9上升到父节点中
节点 9
子节点: [3, 6] [12, 15]
子节点: [1,2][4,5][7,8] [10,11][13,14][16,17]
...
"""
def __init__(self, p_node=None, k_list=[], n=5):
self.k_list = k_list
self.s_list = None
self.p_node = p_node
self.is_leaf = True
if p_node:
self._n = p_node.n
else:
self._n = n
@property
def n(self):
return self._n
def add(self, key):
if not isinstance(key, Data):
key = Data(key)
if not self.is_leaf:
for k_index in range(len(self.k_list)):
if k_index == len(self.k_list) - 1 and key > self.k_list[k_index]:
self.s_list[k_index + 1].add(key)
break
if key < self.k_list[k_index]:
self.s_list[k_index].add(key)
break
else:
if not self.k_list:
self.k_list.append(key)
else:
for k_index in range(len(self.k_list)):
if k_index == len(self.k_list) - 1 and key > self.k_list[k_index]:
self.k_list.append(key)
break
if key < self.k_list[k_index]:
self.k_list.insert(k_index, key)
break
if self._n == len(self.k_list):
self.split()
def addFormSon(self, key, son):
for i_index, key_temp in enumerate(self.k_list):
if key_temp > key:
self.k_list.insert(i_index, key)
self.s_list.insert(i_index + 1, son)
break
else:
self.k_list.append(key)
self.s_list.append(son)
if self._n == len(self.k_list):
self.split()
def split(self):
left = self.k_list[:self._n // 2 + 1]
right = self.k_list[self._n // 2 + 1:]
p_key = left.pop()
if self.p_node:
right_node = BTree(self.p_node, right)
self.k_list = left
if self.s_list:
s_len, l_loss = divmod(len(self.s_list), 2)
self.s_list, right_node.s_list = self.s_list[:s_len + l_loss], self.s_list[s_len + l_loss:]
right_node.is_leaf = self.is_leaf
right_node.update_son()
self.p_node.addFormSon(p_key, right_node)
else:
left_node = BTree(self, left)
right_node = BTree(self, right)
self.k_list = [p_key]
if self.is_leaf:
self.is_leaf = False
else:
s_len, l_loss = divmod(len(self.s_list), 2)
left_node.s_list = self.s_list[:s_len + l_loss]
right_node.s_list = self.s_list[s_len + l_loss:]
left_node.is_leaf = False
right_node.is_leaf = False
left_node.update_son()
right_node.update_son()
self.s_list = [left_node, right_node]
def update_son(self):
for son in self.s_list:
son.p_node = self
def __repr__(self):
rep = ""
for k in self.k_list:
rep = rep + "\t" + k
return rep
def __str__(self):
return str(self.k_list)
def __getitem__(self, item):
if not isinstance(item, Data):
item = Data(item)
for i_dex, k in enumerate(self.k_list):
if k == item:
return k.val
else:
if item < k:
if self.s_list:
return self.s_list[i_dex].__getitem__(item)
else:
if self.s_list:
return self.s_list[-1].__getitem__(item)
class Data:
def __init__(self, data):
if isinstance(data, list):
self.data = data[0]
self.key = hash(data[0])
self.val = data[1]
else:
self.data = data
self.key = hash(data)
def __lt__(self, other):
return self.key < other.key
def __gt__(self, other):
return self.key > other.key
def __eq__(self, other):
return self.key == other.key
def __repr__(self):
return str(self.key)
def test(ls, tree, map, num):
if num is None:
st = uuid.uuid1().hex
else:
st = ls[num]
start = time.time()
ffg = None
for i in ls:
if i[0] == st[0]:
ffg = i[1]
break
print(ffg, " 列表查询耗时:", time.time() - start)
start = time.time()
print(tree[st[0]], "BTree查询耗时:", time.time() - start)
start = time.time()
print(map.get(st[0]), "map查询耗时:", time.time() - start)
print()
if __name__ == '__main__':
vals = [[uuid.uuid1().hex, uuid.uuid1().hex] for i in range(100000)]
b = BTree(n=15)
for i in vals:
b.add(i)
mm = {}
for i in vals:
mm[i[0]] = i[1]
test(vals, b, mm, 10)