algorithm-in-python/dataStructure/intervalTree.py
2019-01-31 12:09:46 +08:00

141 lines
4.1 KiB
Python

''' mbinary
#########################################################################
# File : intervalTree.py
# Author: mbinary
# Mail: zhuheqin1@gmail.com
# Blog: https://mbinary.xyz
# Github: https://github.com/mbinary
# Created Time: 2018-11-18 10:48
# Description:
#########################################################################
'''
from redBlackTree import redBlackTree
from functools import total_ordering
@total_ordering
class node:
def __init__(self,low,high,left=None,right=None,isBlack=False):
self.val = low # self.val is the low
self.high = high
self.max = high
self.left = left
self.right = right
self.parent=None
self.isBlack = isBlack
def __lt__(self,nd):
return self.val < nd.val
def __eq__(self,nd):
return nd is not None and self.val == nd.val
def setChild(self,nd,isLeft = True):
if isLeft: self.left = nd
else: self.right = nd
if nd is not None: nd.parent = self
def getChild(self,isLeft):
if isLeft: return self.left
else: return self.right
def __bool__(self):
return self.val is not None
def __str__(self):
color = 'B' if self.isBlack else 'R'
return f'{color}[{self.val},{self.high}]-{self.max}'
def __repr__(self):
return f'intervalNode({self.val},{self.high},{self.max},isBlack={self.isBlack})'
def overlap(self,low,high):
return self.val<=high and self.high>=low
def setMax(self):
l = 0 if self.left is None else self.left.max
r = 0 if self.right is None else self.right.max
self.max = max(self.high, l, r)
return self.max
class intervalTree(redBlackTree):
def search(self,low,high):
nd = self.root
while nd is not None and not nd.overlap(low,high):
if nd.left is not None and nd.left.max>=low:
nd = nd.left
else:nd = nd.right
return nd
def insert(self,nd):
super(intervalTree,self).insert(nd)
while nd is not None:
nd.setMax()
nd = nd.parent
def delete(self,val):
nd = self.find(val)
if nd is not None:
nd.max = 0
tmp = nd.parent
while tmp is not None:
tmp.setMax()
tmp = tmp.parent
super(intervalTree,self).delete(val)
def rotate(self,prt,chd):
'''rotate prt, and return new prt, namyly the original chd'''
super(intervalTree,self).rotate(prt,chd)
prt.setMax()
chd.setMax()
def copyNode(self,src,des):
des.val = src.val
des.high = src.high
des.setMax()
from random import randint, shuffle
def genNum(n =10,upper=10):
nums ={}
for i in range(n):
while 1:
d = randint(0,100)
if d not in nums:
nums[d] = (d,randint(d,d+upper))
break
return nums.values()
def buildTree(n=10,nums=None,visitor=None):
#if nums is None or nums ==[]: nums = genNum(n)
tree = intervalTree()
print(f'build a red-black tree using {nums}')
for i in nums:
tree.insert(node(*i))
if visitor:
visitor(tree,i)
return tree,nums
def testInsert(nums=None):
def visitor(t,val):
print('inserting', val)
print(t)
tree,nums = buildTree(visitor = visitor,nums=nums)
print('-'*5+ 'in-order visit' + '-'*5)
for i,j in enumerate(tree.sort()):
print(f'{i+1}: {j}')
return tree
def testSuc(nums=None):
tree,nums = buildTree(nums=nums)
for i in tree.sort():
print(f'{i}\'s suc is {tree.getSuccessor(i)}')
def testDelete(nums=None):
tree,nums = buildTree(nums = nums)
print(tree)
for i in nums:
print(f'deleting {i}')
tree.delete(i[0])
print(tree)
return tree
if __name__=='__main__':
lst = [(0,3),(5,8),(6,10),(26,26),(25,30),(8,9),(19,20),(15,23),(16,21),(17,19)]
#lst = None
#testSuc(lst)
tree = testInsert(lst)
#tree,_= buildTree(lst)
while 1:
a =int( input('low:'))
b =int( input('high:'))
res = tree.search(a,b)
print(res)