python实现BTree

使用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  # key list
        self.s_list = None  # 子节点列表
        self.p_node = p_node  # 父节点
        self.is_leaf = True  # 是否是叶子节点
        if p_node:  # n值和父节点保持一致
            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)

    # for i in range(100):
    #     test(vals, b)
    # pass




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
B树是一种常用的数据结构,用于实现数据库中的索引。下面是一个简单的Python实现B树索引的示例: ```python 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 < x.keys[i]: x.keys[i + 1] = x.keys[i] i -= 1 x.keys[i + 1] = k else: while i >= 0 and k < x.keys[i]: i -= 1 i += 1 if len(x.child[i].keys) == (2 * self.t) - 1: self.split_child(x, i) if k > x.keys[i]: 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 search(self, k, x=None): if isinstance(x, BTreeNode): i = 0 while i < len(x.keys) and k > x.keys[i]: i += 1 if i < len(x.keys) and k == x.keys[i]: return x elif x.leaf: return None else: return self.search(k, x.child[i]) else: return self.search(k, self.root) # 使用示例 btree = BTree(3) btree.insert(1) btree.insert(2) btree.insert(3) btree.insert(4) result = btree.search(3) if result: print("Key found!") else: print("Key not found!") ``` 以上是一个简单的B树索引的实现。它包括BTreeNode类和BTree类,可以通过调用insert方法插入键值对,通过调用search方法进行搜索。在使用示例中,我们插入了一些键值对,并搜索了一个存在的键值对。 需要注意的是,这只是一个基本的实现示例,实际应用中可能需要根据具体需求进行适当的改进和优化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值