B+树的python实现

这篇博客介绍了B+树的Python实现,基于极客学院2018年的blog进行修正,解决了Python3语法不兼容和查找算法的bug。作者增加了Size属性以显示插入数据数量,并提供额外测试用例。
摘要由CSDN通过智能技术生成

B+树的python实现

本代码来自极客学院网站死里逃生2018年发表的blog关于 B+tree (附 python 模拟代码)。该代码实现了B+树的插入、删除、范围查找,功能完善,但也存在诸多问题。本文在原代码基础上对其错误进行了修正,更便于需要者使用。

主要贡献

  1. 将python3不支持的语法修改成python3支持的语法,主要是__cmp__修改成__lt__,gt
  2. 解决查找算法bug:当范围查询上界不存在时,原代码返回的查询结果会多出或者缺少元素。点查询则不受影响。
  3. 为B+树类添加了Size成员,可以查看B+树已插入的数据个数
  4. 提供了更多的测试,读者可以利用这些测试检查自己需要的功能是否可以正常实现
  5. 未修复问题:这个插入和删除算法有大问题,插入和删除算法都不会修改上层的键值,除非触发合并或者分裂。
## 使用须知:1. 查找必须得是范围查询,点查询也得是上下界相等才行;查找的返回值一定是一个由KV组成的数组,哪怕点查询
## 2. 删除必须得输入键-值对而不是只靠键,当然如果和查询配合使用还是挺好的;
## 3. 这个算法不会拒绝同一个键多次插入,哪怕值也是相同的也不会报错,照样按从左到右插入
## 4. 注意B+树叶节点不是一个个键值,而是多个键值组成的节点,节点之间才有指向邻居的指针

from collections import deque

def bisect_right(a, x, lo=0, hi=None):
    """Return the index where to insert item x in list a, assuming a is sorted.
    The return value i is such that all e in a[:i] have e <= x, and all e in
    a[i:] have e > x.  So if x already appears in the list, a.insert(x) will
    insert just after the rightmost x already there.
    Optional args lo (default 0) and hi (default len(a)) bound the
    slice of a to be searched.
    """

    if lo < 0:
        raise ValueError('lo must be non-negative')
    if hi is None:
        hi = len(a)
    while lo < hi:
        mid = (lo + hi) // 2
        if x < a[mid]:
            hi = mid
        else:
            lo = mid + 1
    return lo

def bisect_left(a, x, lo=0, hi=None):
    """Return the index where to insert item x in list a, assuming a is sorted.
    The return value i is such that all e in a[:i] have e < x, and all e in
    a[i:] have e >= x.  So if x already appears in the list, a.insert(x) will
    insert just before the leftmost x already there.
    Optional args lo (default 0) and hi (default len(a)) bound the
    slice of a to be searched.
    """

    if lo < 0:
        raise ValueError('lo must be non-negative')
    if hi is None:
        hi = len(a)
    while lo < hi:
        mid = (lo + hi) // 2
        if a[mid] < x:
            lo = mid + 1
        else:
            hi = mid
    return lo

class InitError(Exception):
    pass

class ParaError(Exception):
    pass


class KeyValue(object):
    __slots__ = ('key', 'value')

    def __init__(self, key, value):
        self.key = key
        self.value = value

    def __str__(self):
        return str((self.key, self.value))

    def __eq__(self, other):
        if isinstance(other, KeyValue):
            if self.key == other.key:
                return True
            else:
                return False
        else:
            if self.key == other:
                return True
            else:
                return False

    def __ne__(self, other):
        if isinstance(other, KeyValue):
            if self.key != other.key:
                return True
            else:
                return False
        else:
            if self.key != other:
                return True
            else:
                return False

    def __lt__(self, other):
        if isinstance(other, KeyValue):
            if self.key < other.key:
                return True
            else:
                return False
        else:
            if self.key < other:
                return True
            else:
                return False

    def __gt__(self, other):
        if isinstance(other, KeyValue):
            if self.key > other.key:
                return True
            else:
                return False
        else:
            if self.key > other:
                return True
            else:
                return False


class Bptree_InterNode(object):
    def __init__(self, M):
        if not isinstance(M, int):
            raise InitError('M must be int')
        if M <= 3:
            raise InitError('M must be greater then 3')
        else:
            self.__M = M
            self.clist = []  # 如果是index节点,保存 Bptree_InterNode 节点信息
            #      leaf节点, 保存 Bptree_Leaf的信息
            self.ilist = []  # 保存 索引节点
            self.par = None

    def isleaf(self):
        return False

    def isfull(self):
        return len(self.ilist) >= self
  • 3
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值