B+树删除操作的图形化展示,python调用graphviz自动生成svg图形

本文通过图形化方式展示了B+树删除操作的过程,并基于原作者的Python代码进行了改进,实现了动态变化效果。此外,还提供了代码下载和安装指导。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

引言

在前面的文章《B+树插入操作的图形化展示,python调用graphviz自动生成svg图形》中用图形化的方式展示了B+树在插入时图形的变化。

本文用来展示B+树删除操作的过程。

在网上查到一篇文献《关于 B+tree (附 python 模拟代码)》。该文作者用python实现了B+树的基本操作。但是他的输出结果是文本形式的,不方便直观地查看B+树的动态变化效果。本文在原作者python代码的基础上做了一些改进,实现了图形化展示的效果。对原作者的分享精神,再次表示感谢。

图形化显示环境的搭建细节,还请参看以前的文章《平衡二叉树插入及删除操作的图形化展示,python调用graphviz自动生成svg图形
对svg图形做美化处理的细节,还请参看以前的文章《用jquery对graphviz生成的svg图形做后处理,改变字体,颜色,连线形状等

图形化效果

下面是插入一个随机选定的key序列[10, 17, 9, 33, 33, 50, 36, 41, 31, 30, 13, 6, 37, 45, 20, 4, 35, 11, 2, 40] 生成一棵B+树后再进行删除操作的图文演示
在这里插入图片描述
其它序列的插入过程的图形效果,可以将代码下载到本地后自已手动调整源码,然后在浏览器上查看图形效果。当然前提是你的电脑上已经安装好了python与graphviz。

完整的python代码

BplusTree.py

# -*- coding:utf-8 -*- 
# B+树的序列化
# 原作者:thursdayhawk http://wiki.jikexueyuan.com/project/python-actual-combat/tutorial-11.html
# 修改成用graphviz图形化显示,添加了序列化为json格式文件的功能,修改者:littleZhuHui

import os
import json
from random import randint,choice
from bisect import bisect_right,bisect_left
from collections import deque

#显示信息的级别,控制不同等级的信息的可见性
infoLevel = 1

# id值为1的节点是 superRoot,是所有操作的起点,
#因此固定为1,而0表示找不到有效的节点
idSeed = 1

#存放已加载节点的hash表,由节点id映射到节点对象
nodePool ={
   
   }

#生成一个全局ID                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
def  getGID():
    global idSeed
    idSeed+=1
    return idSeed

#------------------ node 定义开始 ----------------------------------------------

class InitError(Exception):
    pass

class LoadNodeError(Exception):
    pass

class ParaError(Exception):
    pass

# 定义键值对(为了处理重复键值,对kv类做改进,使得一个key可以对应多个value)
class KeyValue(object):
    __slots__=('key','valueList')
    def __init__(self,key,value):
        self.key=key
        self.valueList=[value]        
    def __str__(self):
        return '%s,%s'%(self.key,str([v for v in self.valueList]))
    def __cmp__(self,key):
        if self.key>key:
            return 1
        elif self.key==key:
            return 0
        else:
            return -1
    def appendValue(self,value):
        self.valueList.insert(0,value)
    @property
    def value(self): #默认value就是list中的第0个value       
        return self.valueList[0]
    @property
    def vLen(self):     
        return len(self.valueList)

# 定义可按下标进行控制访问的childList类
# 不直接使用列表而用自定义对象表示childList ,主要原因有两点
# 按需加载,孩子节点序列化时存放的节点Id值,当实际访问时加载为对象
# 访问控制,当修改了孩子节点指针的值之后,可以有机会做更多的处理(可以实现事件钩子功能)
class ChildList(object):
    def __init__(self,listVal=[]): 
        self._childList = listVal

    def __getitem__(self,i):          
        if type(self._childList[i])==type(0): #需要加载
            self._childList[i] = loadNode(self._childList[i])
        return self._childList[i]
       
    def __setitem__(self,i,value): 
        self._childList[i] = value

    def index(self,value): 
        return self._childList.index(value)

    def insert(self,i,value): 
        return self._childList.insert(i,value)

    def remove(self,value): 
        return self._childList.remove(value)

    def pop(self): 
        return self._childList.pop()
       
# 内部节点
class Bptree_InterNode(object):

    def __init__(self,M,id=-1):
        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.childList=ChildList()
            self.indexList=[]
            self._bro=-1
            self._par=None
            #每个节点有一个唯一的整数值做为id,方便用graphviz绘图
            if id < 0:
                self.id = getGID()
            else:
                self.id = id

    def isleaf(self):
        return False

    def isfull(self):
        return len(self.indexList)>=self.M-1

    def isempty(self):
        return len(self.indexList)<=(self.M+1)/2-1

    @property
    def bro(self):
        if type(self._bro)==type(0): #需要加载
            if self._bro > 1 : # 确实对应着一个节点,1是超级根节点,不算在内
                self._bro = loadNode(self._bro)
        return self._bro

    @bro.setter
    def bro(self,value):
        #可在此处做一些额外的处理
        self._bro=value

    @property
    def par(self):
        if type(self._par)==type(0): #需要加载
            if self._bro > 1 :
                self._par = loadNode(self._par)
        return self._par

    @par.setter
    def par(self,value):
        #可在此处做一些额外的处理
        self._par=value

#叶子节点       
class Bptree_Leaf(object):

    def __init__(self,L,id=-1):
        if not isinstance(L,int):
            raise InitError,'L must be int'
        else:
            self.L=L
            #self.childList='<br>\nleaf has no child list<br>\n'
            self.kvList=[]
            self._bro=0
            self._par=None
            #每个节点有一个唯一的整数值做为id,方便用graphviz绘图
            if id < 0:
                self.id = getGID
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值