#!/usr/bin/env python
from random import randint, choice
from bisect import bisect_right, bisect_left
from collections import deque
 
class InitError(Exception):
    pass
class ParaError(Exception):
    pass
 
#生成键值对
class KeyValue(object):
    __slots__=('key', 'value')
    def __init__(self, key, value):
        self.key=int(key) #一定要保证键值是整型
        self.value=value
        
    def __str__(self):
        return str((self.key, self.value))
    
    def __cmp__(self, key):
        if self.key>key:
            return 1
        elif self.key < key:
            return -1
        else:
            return 0
    
    def __lt__(self, other):
        if (type(self) == type(other)):
            return self.key < other.key;
        else:
            return int(self.key) < int(other);
            
    def __eq__(self, other):
        if (type(self) == type(other)):
            return self.key == other.key;
        else:
            return int(self.key) == int(other);
 
    def __gt__(self, other):
        return not self < other;   
        
 
#B+树实现
#实现过程和btree很像,不过有几点显著不同。
#1.内节点不存储key-value,只存放key
#
#2.沿着内节点搜索的时候,查到索引相等的数要向树的右边走。所以二分查找要选择
#bisect_right
#
#3.在叶子节点满的时候,并不是先分裂再插入而是先插入再分裂。因为b+tree无法保证
#分裂的两个节点的大小都是相等的。在奇数大小的数据分裂的时候右边的子节点会比左
#边的大。如果先分裂再插入无法保证插入的节点一定会插在数量更少的子节点上,满足
#节点数量平衡的条件。
#
#4.在删除数据的时候,b+tree的左右子节点借数据的方式比btree更加简单有效,只把子
#节点的子树直接剪切过来,再把索引变一下就行了,而且叶子节点的兄弟指针也不用动。
#
class Bptree(object):
    class __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=[] #存放区间
                self.ilist=[] #存放索引/序号
                self.par=None
        def isleaf(self):
            return False
        def isfull(self):
            return len(self.ilist)>=self.M-1
        def isempty(self):
            return len(self.ilist)<=(self.M+1)/2-1
        @property
        def M(self):
            return self.__M
 
    #叶子
    class __Leaf(object):
        def __init__(self,L):
            if not isinstance(L,int):
                raise InitError('L must be int')
            else:
                self.__L=L
                self.vlist=[]
                self.bro=None #兄弟结点
                self.par=None #父结点
        def isleaf(self):
            return True
        def isfull(self):
            return len(self.vlist)>self.L
        def isempty(self):
            return len(self.vlist)<=(self.L+1)/2
        @property
        def L(self):
            return self.__L
 
    #初始化
    def __init__(self,M,L):
        if L>M:
            raise InitError('L must be less or equal then M')
        else:
            self.__M=M
            self.__L=L
            self.__root=Bptree.__Leaf(L)
            self.__leaf=self.__root
    @property
    def M(self):
        return self.__M
    @property
    def L(self):
        return self.__L
 
    #插入
    def insert(self, key_value):
        node=self.__root
        def split_node(n1):
            mid=self.M//2 #此处注意,可能出错
            newnode=Bptree.__InterNode(self.M)
            newnode.ilist=n1.ilist[mid:]
            newnode.clist=n1.clist[mid:]
            newnode.par=n1.par
            for c in newnode.clist:
                c.par=newnode
            if n1.par is None:
                newroot=Bptree.__InterNode(self.M)
                newroot.ilist=[n1.ilist[mid-1]]
                newroot.clist=[n1,newnode]
                n1.par=newnode.par=newroot
                self.__root=newroot
            else:
                i=n1.par.clist.index(n1)
                n1.par.ilist.insert(i,n1.ilist[mid-1])
                n1.par.clist.insert(i+1,newnode)
            n1.ilist=n1.ilist[:mid-1]
            n1.clist=n1.clist[:mid]
            return n1.par
        def split_leaf(n2):
            mid=(self.L+1)//2
            newleaf=Bptree.__Leaf(self.L)
            newleaf.vlist=n2.vlist[mid:]
            if n2.par==None:
                newroot=Bptree.__InterNode(self.M)
                newroot.ilist=[n2.vlist[mid].key]
                newroot.clist=[n2,newleaf]
                n2.par=newleaf.par=newroot
                self.__root=newroot
            else:
                i=n2.par.clist.index(n2)
                n2.par.ilist.insert(i,n2.vlist[mid].key)
                n2.par.clist.insert(i+1,newleaf)
                newleaf.par=n2.par
            n2.vlist=n2.vlist[:mid]
            n2.bro=newleaf
        def insert_node(n):
            if not n.isleaf():
                if n.isfull():
                    insert_node(split_node(n))
                else:
                    p=bisect_right(n.ilist,key_value)
                    insert_node(n.clist[p])
            else:
                p=bisect_right(n.vlist,key_value)
                n.vlist.insert(p,key_value)
                if n.isfull():
                    split_leaf(n)
                else:
                    return
        insert_node(node)
 
    #搜索
    def search(self,mi=None,ma=None):
        result=[]
        node=self.__root
        leaf=self.__leaf
        if mi is None or ma is None:
            raise ParaError('you need to setup searching range')
        elif mi > ma:
            raise ParaError('upper bound must be greater or equal than lower bound')
        def search_key(n,k):
            if n.isleaf():
                p=bisect_left(n.vlist,k)
                return (p,n)
            else:
                p=bisect_right(n.ilist,k)
                return search_key(n.clist[p],k)
        if mi is None:
            while True:
                for kv in leaf.vlist:
                    if kv<=ma:
                        result.append(kv)
                    else:
                        return result
                if leaf.bro==None:
                    return result
                else:
                    leaf=leaf.bro
        elif ma is None:
            index,leaf=search_key(node,mi)
            result.extend(leaf.vlist[index:])
            while True:
                if leaf.bro==None:
                    return result
                else:
                    leaf=leaf.bro
                    result.extend(leaf.vlist)
        else:
            if mi==ma:
                i,l=search_key(node,mi)
                try:
                    if l.vlist[i]==mi:
                        result.append(l.vlist[i])
                        return result
                    else:
                        return result
                except IndexError:
                    return result
            else:
                i1,l1=search_key(node,mi)
                i2,l2=search_key(node,ma)
                if l1 is l2:
                    if i1==i2:
                        return result
                    else:
                        result.extend(l2.vlist[i1:i2])
                        return result
                else:
                    result.extend(l1.vlist[i1:])
                    l=l1
                    while True:                        
                        if l.bro==l2:
                            result.extend(l2.vlist[:i2])
                            return result
                        elif l.bro != None:
                            result.extend(l.bro.vlist)
                            l=l.bro
                        else:
                            return result;
    def traversal(self):
        result=[]
        l=self.__leaf
        while True:
            result.extend(l.vlist)
            if l.bro==None:
                return result
            else:
                l=l.bro
    def show(self):
        print('this b+tree is:\n')
        q=deque()
        h=0
        q.append([self.__root,h])
        while True:
            try:
                w,hei=q.popleft()
            except IndexError:
                return
            else:
                if not w.isleaf():
                    print(w.ilist,'the height is',hei)
                    if hei==h:
                        h+=1
                    q.extend([[i,h] for i in w.clist])
                else:
                    print([(v.key,v.value) for v in w.vlist],'the leaf is,',hei)
 
    #删除                                                                                                                                                                                                                                                                                                                          
    def delete(self,key_value):
        def merge(n,i):
            if n.clist[i].isleaf():
                n.clist[i].vlist=n.clist[i].vlist+n.clist[i+1].vlist
                n.clist[i].bro=n.clist[i+1].bro
            else:
                n.clist[i].ilist=n.clist[i].ilist+[n.ilist[i]]+n.clist[i+1].ilist
                n.clist[i].clist=n.clist[i].clist+n.clist[i+1].clist
            n.clist.remove(n.clist[i+1])
            n.ilist.remove(n.ilist[i])
            if n.ilist==[]:
                n.clist[0].par=None
                self.__root=n.clist[0]
                del n
                return self.__root
            else:
                return n
        def tran_l2r(n,i):
            if not n.clist[i].isleaf():
                n.clist[i+1].clist.insert(0,n.clist[i].clist[-1])
                n.clist[i].clist[-1].par=n.clist[i+1]
                n.clist[i+1].ilist.insert(0,n.ilist[i])
                n.ilist[i]=n.clist[i].ilist[-1]
                n.clist[i].clist.pop()
                n.clist[i].ilist.pop()
            else:
                n.clist[i+1].vlist.insert(0,n.clist[i].vlist[-1])
                n.clist[i].vlist.pop()
                n.ilist[i]=n.clist[i+1].vlist[0].key
        def tran_r2l(n,i):
            if not n.clist[i].isleaf():
                n.clist[i].clist.append(n.clist[i+1].clist[0])
                n.clist[i+1].clist[0].par=n.clist[i]
                n.clist[i].ilist.append(n.ilist[i])
                n.ilist[i]=n.clist[i+1].ilist[0]
                n.clist[i+1].clist.remove(n.clist[i+1].clist[0])
                n.clist[i+1].ilist.remove(n.clist[i+1].ilist[0])
            else:
                n.clist[i].vlist.append(n.clist[i+1].vlist[0])
                n.clist[i+1].vlist.remove(n.clist[i+1].vlist[0])
                n.ilist[i]=n.clist[i+1].vlist[0].key
        def del_node(n,kv):
            if not n.isleaf():
                p=bisect_right(n.ilist,kv)
                if p==len(n.ilist):
                    if not n.clist[p].isempty():
                        return del_node(n.clist[p],kv)
                    elif not n.clist[p-1].isempty():
                        tran_l2r(n,p-1)
                        return del_node(n.clist[p],kv)
                    else:
                        return del_node(merge(n,p),kv)
                else:
                    if not n.clist[p].isempty():
                        return del_node(n.clist[p],kv)
                    elif not n.clist[p+1].isempty():
                        tran_r2l(n,p)
                        return del_node(n.clist[p],kv)
                    else:
                        return del_node(merge(n,p),kv)
            else:
                p=bisect_left(n.vlist,kv)
                try:
                    pp=n.vlist[p]
                except IndexError:
                    return -1
                else:
                    if pp!=kv:
                        return -1
                    else:
                        n.vlist.remove(kv)
                        return 0
        del_node(self.__root,key_value)
 
        
def test():
    #初始化数据源
    mini=50
    maxi=200
    testlist=[]
    for i in range(20):
        key=randint(1,1000)
        #key=i
        value=choice(['Do', 'Re', 'Mi', 'Fa', 'So', 'La', 'Si'])
        testlist.append(KeyValue(key,value))
 
    #初始化B树
    mybptree=Bptree(4, 4)
 
    #插入操作
    for x in testlist:
        mybptree.insert(x)
 
    mybptree.show()
 
    #查找操作
    print('\nnow we are searching item between %d and %d\n==>'%(mini,maxi))
    print([v.key for v in mybptree.search(mini,maxi)])
 
    
    #删除操作
    mybptree.delete(testlist[0])
    print('\n删除 {0}后, the newtree is:\n'.format(testlist[0]));
    mybptree.show()
 
    
    #深度遍历操作
    print('\nkey of this b+tree is \n')
    print([kv.key for kv in mybptree.traversal()])
    
    
 
 
if __name__ == '__main__':
    test();
 
 
 
 
1. #!/usr/bin/env python
2.  
from random import
3.  
from bisect import
4.  
from collections import
5.   
6.  
class InitError(Exception):
7.  
pass
8.  
class ParaError(Exception):
9.  
pass
10.   
11.  
#生成键值对
12.  
class KeyValue(object):
13.  
'key', 'value')
14.  
def __init__(self, key, value):
15.  
#一定要保证键值是整型
16.  
        self.value=value
17.   
18.  
def __str__(self):
19.  
return
20.   
21.  
def __cmp__(self, key):
22.  
if
23.  
return 1
24.  
elif
25.  
return -1
26.  
else:
27.  
return 0
28.   
29.  
def __lt__(self, other):
30.  
if
31.  
return
32.  
else:
33.  
return
34.   
35.  
def __eq__(self, other):
36.  
if
37.  
return
38.  
else:
39.  
return
40.   
41.  
def __gt__(self, other):
42.  
return not
43.   
44.   
45.  
#B+树实现
46.  
#实现过程和btree很像,不过有几点显著不同。
47.  
#1.内节点不存储key-value,只存放key
48.  
#
49.  
#2.沿着内节点搜索的时候,查到索引相等的数要向树的右边走。所以二分查找要选择
50.  
#bisect_right
51.  
#
52.  
#3.在叶子节点满的时候,并不是先分裂再插入而是先插入再分裂。因为b+tree无法保证
53.  
#分裂的两个节点的大小都是相等的。在奇数大小的数据分裂的时候右边的子节点会比左
54.  
#边的大。如果先分裂再插入无法保证插入的节点一定会插在数量更少的子节点上,满足
55.  
#节点数量平衡的条件。
56.  
#
57.  
#4.在删除数据的时候,b+tree的左右子节点借数据的方式比btree更加简单有效,只把子
58.  
#节点的子树直接剪切过来,再把索引变一下就行了,而且叶子节点的兄弟指针也不用动。
59.  
#
60.  
class Bptree(object):
61.  
class __InterNode(object):
62.  
def __init__(self, M):
63.  
if not
64.  
raise InitError('M must be int')
65.  
if M<=3:
66.  
raise InitError('M must be greater then 3')
67.  
else:
68.  
                self.__M=M
69.  
#存放区间
70.  
#存放索引/序号
71.  
None
72.  
def isleaf(self):
73.  
return False
74.  
def isfull(self):
75.  
return len(self.ilist)>=self.M-1
76.  
def isempty(self):
77.  
return len(self.ilist)<=(self.M+1)/2-1
78.  
        @property
79.  
def M(self):
80.  
return
81.   
82.  
#叶子
83.  
class __Leaf(object):
84.  
def __init__(self,L):
85.  
if not
86.  
raise InitError('L must be int')
87.  
else:
88.  
                self.__L=L
89.  
                self.vlist=[]
90.  
None #兄弟结点
91.  
None #父结点
92.  
def isleaf(self):
93.  
return True
94.  
def isfull(self):
95.  
return
96.  
def isempty(self):
97.  
return len(self.vlist)<=(self.L+1)/2
98.  
        @property
99.  
def L(self):
100.  
return
101.   
102.  
#初始化
103.  
def __init__(self,M,L):
104.  
if
105.  
raise InitError('L must be less or equal then M')
106.  
else:
107.  
            self.__M=M
108.  
            self.__L=L
109.  
            self.__root=Bptree.__Leaf(L)
110.  
            self.__leaf=self.__root
111.  
    @property
112.  
def M(self):
113.  
return
114.  
    @property
115.  
def L(self):
116.  
return
117.   
118.  
#插入
119.  
def insert(self, key_value):
120.  
        node=self.__root
121.  
def split_node(n1):
122.  
2 #此处注意,可能出错
123.  
            newnode=Bptree.__InterNode(self.M)
124.  
            newnode.ilist=n1.ilist[mid:]
125.  
            newnode.clist=n1.clist[mid:]
126.  
            newnode.par=n1.par
127.  
for c in
128.  
                c.par=newnode
129.  
if n1.par is None:
130.  
                newroot=Bptree.__InterNode(self.M)
131.  
-1]]
132.  
                newroot.clist=[n1,newnode]
133.  
                n1.par=newnode.par=newroot
134.  
                self.__root=newroot
135.  
else:
136.  
                i=n1.par.clist.index(n1)
137.  
-1])
138.  
1,newnode)
139.  
-1]
140.  
            n1.clist=n1.clist[:mid]
141.  
return
142.  
def split_leaf(n2):
143.  
1)//2
144.  
            newleaf=Bptree.__Leaf(self.L)
145.  
            newleaf.vlist=n2.vlist[mid:]
146.  
if n2.par==None:
147.  
                newroot=Bptree.__InterNode(self.M)
148.  
                newroot.ilist=[n2.vlist[mid].key]
149.  
                newroot.clist=[n2,newleaf]
150.  
                n2.par=newleaf.par=newroot
151.  
                self.__root=newroot
152.  
else:
153.  
                i=n2.par.clist.index(n2)
154.  
                n2.par.ilist.insert(i,n2.vlist[mid].key)
155.  
1,newleaf)
156.  
                newleaf.par=n2.par
157.  
            n2.vlist=n2.vlist[:mid]
158.  
            n2.bro=newleaf
159.  
def insert_node(n):
160.  
if not
161.  
if
162.  
                    insert_node(split_node(n))
163.  
else:
164.  
                    p=bisect_right(n.ilist,key_value)
165.  
                    insert_node(n.clist[p])
166.  
else:
167.  
                p=bisect_right(n.vlist,key_value)
168.  
                n.vlist.insert(p,key_value)
169.  
if
170.  
                    split_leaf(n)
171.  
else:
172.  
return
173.  
        insert_node(node)
174.   
175.  
#搜索
176.  
def search(self,mi=None,ma=None):
177.  
        result=[]
178.  
        node=self.__root
179.  
        leaf=self.__leaf
180.  
if mi is None or ma is None:
181.  
raise ParaError('you need to setup searching range')
182.  
elif
183.  
raise ParaError('upper bound must be greater or equal than lower bound')
184.  
def search_key(n,k):
185.  
if
186.  
                p=bisect_left(n.vlist,k)
187.  
return
188.  
else:
189.  
                p=bisect_right(n.ilist,k)
190.  
return
191.  
if mi is None:
192.  
while True:
193.  
for kv in
194.  
if
195.  
                        result.append(kv)
196.  
else:
197.  
return
198.  
if leaf.bro==None:
199.  
return
200.  
else:
201.  
                    leaf=leaf.bro
202.  
elif ma is None:
203.  
            index,leaf=search_key(node,mi)
204.  
            result.extend(leaf.vlist[index:])
205.  
while True:
206.  
if leaf.bro==None:
207.  
return
208.  
else:
209.  
                    leaf=leaf.bro
210.  
                    result.extend(leaf.vlist)
211.  
else:
212.  
if
213.  
                i,l=search_key(node,mi)
214.  
try:
215.  
if
216.  
                        result.append(l.vlist[i])
217.  
return
218.  
else:
219.  
return
220.  
except
221.  
return
222.  
else:
223.  
                i1,l1=search_key(node,mi)
224.  
                i2,l2=search_key(node,ma)
225.  
if l1 is
226.  
if
227.  
return
228.  
else:
229.  
                        result.extend(l2.vlist[i1:i2])
230.  
return
231.  
else:
232.  
                    result.extend(l1.vlist[i1:])
233.  
                    l=l1
234.  
while True:                        
235.  
if
236.  
                            result.extend(l2.vlist[:i2])
237.  
return
238.  
elif l.bro != None:
239.  
                            result.extend(l.bro.vlist)
240.  
                            l=l.bro
241.  
else:
242.  
return
243.  
def traversal(self):
244.  
        result=[]
245.  
        l=self.__leaf
246.  
while True:
247.  
            result.extend(l.vlist)
248.  
if l.bro==None:
249.  
return
250.  
else:
251.  
                l=l.bro
252.  
def show(self):
253.  
'this b+tree is:\n')
254.  
        q=deque()
255.  
0
256.  
        q.append([self.__root,h])
257.  
while True:
258.  
try:
259.  
                w,hei=q.popleft()
260.  
except
261.  
return
262.  
else:
263.  
if not
264.  
'the height is',hei)
265.  
if
266.  
1
267.  
for i in
268.  
else:
269.  
for v in w.vlist],'the leaf is,',hei)
270.   
271.  
#删除                                                                                                                                                                                                                                                                                                                          
272.  
def delete(self,key_value):
273.  
def merge(n,i):
274.  
if
275.  
1].vlist
276.  
1].bro
277.  
else:
278.  
1].ilist
279.  
1].clist
280.  
1])
281.  
            n.ilist.remove(n.ilist[i])
282.  
if
283.  
0].par=None
284.  
0]
285.  
del
286.  
return
287.  
else:
288.  
return
289.  
def tran_l2r(n,i):
290.  
if not
291.  
1].clist.insert(0,n.clist[i].clist[-1])
292.  
-1].par=n.clist[i+1]
293.  
1].ilist.insert(0,n.ilist[i])
294.  
-1]
295.  
                n.clist[i].clist.pop()
296.  
                n.clist[i].ilist.pop()
297.  
else:
298.  
1].vlist.insert(0,n.clist[i].vlist[-1])
299.  
                n.clist[i].vlist.pop()
300.  
1].vlist[0].key
301.  
def tran_r2l(n,i):
302.  
if not
303.  
1].clist[0])
304.  
1].clist[0].par=n.clist[i]
305.  
                n.clist[i].ilist.append(n.ilist[i])
306.  
1].ilist[0]
307.  
1].clist.remove(n.clist[i+1].clist[0])
308.  
1].ilist.remove(n.clist[i+1].ilist[0])
309.  
else:
310.  
1].vlist[0])
311.  
1].vlist.remove(n.clist[i+1].vlist[0])
312.  
1].vlist[0].key
313.  
def del_node(n,kv):
314.  
if not
315.  
                p=bisect_right(n.ilist,kv)
316.  
if
317.  
if not
318.  
return
319.  
elif not n.clist[p-1].isempty():
320.  
-1)
321.  
return
322.  
else:
323.  
return
324.  
else:
325.  
if not
326.  
return
327.  
elif not n.clist[p+1].isempty():
328.  
                        tran_r2l(n,p)
329.  
return
330.  
else:
331.  
return
332.  
else:
333.  
                p=bisect_left(n.vlist,kv)
334.  
try:
335.  
                    pp=n.vlist[p]
336.  
except
337.  
return -1
338.  
else:
339.  
if
340.  
return -1
341.  
else:
342.  
                        n.vlist.remove(kv)
343.  
return 0
344.  
        del_node(self.__root,key_value)
345.   
346.   
347.  
def test():
348.  
#初始化数据源
349.  
50
350.  
200
351.  
    testlist=[]
352.  
for i in range(20):
353.  
1,1000)
354.  
#key=i
355.  
'Do', 'Re', 'Mi', 'Fa', 'So', 'La', 'Si'])
356.  
        testlist.append(KeyValue(key,value))
357.   
358.  
#初始化B树
359.  
4, 4)
360.   
361.  
#插入操作
362.  
for x in
363.  
        mybptree.insert(x)
364.   
365.  
    mybptree.show()
366.   
367.  
#查找操作
368.  
'\nnow we are searching item between %d and %d\n==>'%(mini,maxi))
369.  
for v in
370.   
371.   
372.  
#删除操作
373.  
0])
374.  
'\n删除 {0}后, the newtree is:\n'.format(testlist[0]));
375.  
    mybptree.show()
376.   
377.   
378.  
#深度遍历操作
379.  
'\nkey of this b+tree is \n')
380.  
for kv in
381.   
382.   
383.   
384.   
385.  
if __name__ == '__main__':
386.  
    test();
387.