设为首页 收藏本站
查看: 965|回复: 0

[经验分享] Python版B树

[复制链接]

尚未签到

发表于 2017-4-27 07:50:12 | 显示全部楼层 |阅读模式
话说以前的树都用java写的,最近发现python有点生疏了,于是用python写了个B树实现,B树在索引领域用得还是蛮多了,如果没记错mysql的默认索引好像就是B树...
首先是数据实体对象,很简单,只存放key,value

class Entity(object):
'''数据实体'''
def __init__(self,key,value):
self.key = key
self.value = value


然后节点对象

class Node(object):
'''B树的节点'''
def __init__(self):
self.parent = None
self.entitys = []
self.childs = []
def find(self,key):
'''通过key查找并返回一个数据实体'''
for e in self.entitys:
if key == e.key:
return e

def delete(self,key):
'''通过key删除一个数据实体,并返回它和它的下标(下标,实体)'''
for i,e in enumerate(self.entitys):
if e.key == key:
del self.entitys
return (i,e)

def isLeaf(self):
'''判断该节点是否是一个叶子节点'''
return len(self.childs) == 0

def addEntity(self,entity):
'''添加一个数据实体'''
self.entitys.append(entity)
self.entitys.sort(key=lambda x:x.key)

def addChild(self,node):
'''添加一个子节点'''
self.childs.append(node)
node.parent = self
self.childs.sort(key=lambda x:x.entitys[0].key)


最后是Tree类

class Tree(object):
'''B树'''
def __init__(self,size=6):
self.size = size
self.root = None
self.length = 0

def add(self,key,value=None):
'''插入一条数据到B树'''
self.length += 1
if self.root:
current = self.root
while not current.isLeaf():
for i,e in enumerate(current.entitys):
if e.key > key:
current = current.childs
break
elif e.key == key:
e.value = value
self.length -= 1
return
else:
current = current.childs[-1]
current.addEntity(Entity(key,value))
if len(current.entitys) > self.size:
self.__spilt(current)
else:
self.root = Node()
self.root.addEntity(Entity(key,value))

def get(self,key):
'''通过key查询一个数据'''
node = self.__findNode(key)
if node:  
return node.find(key).value

def delete(self,key):
'''通过key删除一个数据项并返回它'''
node = self.__findNode(key)
if node:
i,e = node.delete(key)
#在节点不是叶子节点时需要做修复(取对应下标的子节点的最大的一个数据项来补)
if not node.isLeaf():
child = node.childs
j,entity = child.delete(child.entitys[-1].key)
node.addEntity(entity)
while not child.isLeaf():
node = child
child = child.childs[j]
j,entity = child.delete(child.entitys[-1].key)
node.addEntity(entity)
self.length -= 1
return e.value

def isEmpty(self):
return self.length == 0

def __findNode(self, key):
'''通过key值查询一个数据在哪个节点,找到就返回该节点'''
if self.root:
current = self.root
while not current.isLeaf():
for i, e in enumerate(current.entitys):
if e.key > key:
current = current.childs
break
elif e.key == key:
return current
else:
current = current.childs[-1]
if current.find(key):
return current

def __spilt(self,node):
'''
分裂一个节点,规则为:
1、中间的数据项移到父节点
2、新建一个右兄弟节点,将中间节点右边的数据项移到新节点
'''
middle = len(node.entitys) / 2
top = node.entitys[middle]
right = Node()
for e in node.entitys[middle + 1:]:
right.addEntity(e)
for n in node.childs[middle + 1:]:
right.addChild(n)
node.entitys = node.entitys[:middle]
node.childs = node.childs[:middle + 1]
parent = node.parent
if parent:
parent.addEntity(top)
parent.addChild(right)
if len(parent.entitys) > self.size:
self.__spilt(parent)
else:
self.root = Node()
self.root.addEntity(top)
self.root.addChild(node)
self.root.addChild(right)


测试代码

if __name__ == '__main__':
t = Tree(4)
t.add(20)
t.add(40)
t.add(60)
t.add(70,'c')
t.add(80)      
t.add(10)
t.add(30)
t.add(15,'python')
t.add(75,'java')
t.add(85)
t.add(90)
t.add(25)
t.add(35,'c#')
t.add(50)
t.add(22,'c++')
t.add(27)
t.add(32)
print t.get(15)
print t.get(75)
print t.delete(35)
print t.delete(22)
t.add(22,'lua')
print t.get(22)
print t.length

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-369680-1-1.html 上篇帖子: Python 监控 Data Guard 脚本 下篇帖子: Python 客户端Socket编程
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表