Update bloomFilter, cantor, redblackTrue,matrix_chain_multiply

This commit is contained in:
mbinary 2018-11-07 16:52:55 +08:00
parent 0c08851597
commit d1cf579a2b
14 changed files with 1107 additions and 485 deletions

3
.gitignore vendored
View File

@ -1,5 +1,6 @@
.* .*
*.o *.o
*.exe *.exe
__pycache__/** __pycache__
!.gitignore !.gitignore
*.out

View File

@ -1,4 +1,4 @@
# Algorithm and Data Structures # Algorithm
>Notes and codes for learning algorithm and data structures :smiley: >Notes and codes for learning algorithm and data structures :smiley:
Some pictures and ideas are from `<<Introduction to Algotithm>> Some pictures and ideas are from `<<Introduction to Algotithm>>

View File

@ -0,0 +1,122 @@
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}')
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)
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)
#testInsert(lst)
testDelete(lst)

View File

@ -9,18 +9,6 @@
# Description: # Description:
######################################################################### #########################################################################
''' '''
'''
#########################################################################
# File : redBlackTree.py
# Author: mbinary
# Mail: zhuheqin1@gmail.com
# Blog: https://mbinary.coding.me
# Github: https://github.com/mbinary
# Created Time: 2018-07-12 20:34
# Description:
#########################################################################
'''
from functools import total_ordering from functools import total_ordering
from random import randint, shuffle from random import randint, shuffle
@ -30,14 +18,17 @@ class node:
self.val =val self.val =val
self.left = left self.left = left
self.right = right self.right = right
self.parent= None
self.isBlack = isBlack self.isBlack = isBlack
def __lt__(self,nd): def __lt__(self,nd):
return self.val < nd.val return self.val < nd.val
def __eq__(self,nd): def __eq__(self,nd):
return nd is not None and self.val == nd.val return nd is not None and self.val == nd.val
def setChild(self,nd,isLeft = True): def setChild(self,nd,isLeft):
if isLeft: self.left = nd if isLeft: self.left = nd
else: self.right = nd else: self.right = nd
if nd is not None: nd.parent = self
def getChild(self,isLeft): def getChild(self,isLeft):
if isLeft: return self.left if isLeft: return self.left
else: return self.right else: return self.right
@ -45,7 +36,8 @@ class node:
return self.val is not None return self.val is not None
def __str__(self): def __str__(self):
color = 'B' if self.isBlack else 'R' color = 'B' if self.isBlack else 'R'
return f'{color}-{self.val:}' val = '-' if self.parent==None else self.parent.val
return f'{color}-{self.val}'
def __repr__(self): def __repr__(self):
return f'node({self.val},isBlack={self.isBlack})' return f'node({self.val},isBlack={self.isBlack})'
class redBlackTree: class redBlackTree:
@ -63,6 +55,159 @@ class redBlackTree:
if isBlack is None or isBlack: if isBlack is None or isBlack:
nd.isBlack = True nd.isBlack = True
else:nd.isBlack = False else:nd.isBlack = False
def setRoot(self,nd):
if nd is not None: nd.parent=None
self.root= nd
def find(self,val):
nd = self.root
while nd:
if nd.val ==val:
return nd
else:
nd = nd.getChild(nd.val>val)
def getSuccessor(self,nd):
if nd:
if nd.right:
nd = nd.right
while nd.left:
nd = nd.left
return nd
else:
while nd.parent is not None and nd.parent.right is nd:
nd = nd.parent
return None if nd is self.root else nd.parent
def rotate(self,prt,chd):
'''rotate prt with the center of chd'''
if self.root is prt:
self.setRoot(chd)
else:
prt.parent.setChild(chd, prt.parent.left is prt)
isLeftChd = prt.left is chd
prt.setChild(chd.getChild(not isLeftChd), isLeftChd)
chd.setChild(prt,not isLeftChd)
def insert(self,nd):
if nd.isBlack: nd.isBlack = False
if self.root is None:
self.setRoot(nd)
self.root.isBlack = True
else:
parent = self.root
while parent:
if parent == nd : return None
isLeft = parent > nd
chd = parent.getChild(isLeft)
if chd is None:
parent.setChild(nd,isLeft)
break
else:
parent = chd
self.fixUpInsert(parent,nd)
def fixUpInsert(self,parent,nd):
''' adjust color and level, there are two red nodes: the new one and its parent'''
while not self.checkBlack(parent):
grand = parent.parent
isLeftPrt = grand.left is parent
uncle = grand.getChild(not isLeftPrt)
if not self.checkBlack(uncle):
# case 1: new node's uncle is red
self.setBlack(grand, False)
self.setBlack(grand.left, True)
self.setBlack(grand.right, True)
nd = grand
parent = nd.parent
else:
# case 2: new node's uncle is black(including nil leaf)
isLeftNode = parent.left is nd
if isLeftNode ^ isLeftPrt:
# case 2.1 the new node is inserted in left-right or right-left form
# grand grand
# parent or parent
# nd nd
self.rotate(parent,nd) #parent rotate
nd,parent = parent,nd
# case 3 (case 2.2) the new node is inserted in left-left or right-right form
# grand grand
# parent or parent
# nd nd
self.setBlack(grand, False)
self.setBlack(parent, True)
self.rotate(grand,parent)
self.setBlack(self.root,True)
def copyNode(self,src,des):
'''when deleting a node which has two kids,
copy its succesor's data to his position
data exclude left, right , isBlack
'''
des.val = src.val
def delete(self,val):
'''delete node in a binary search tree'''
if isinstance(val,node): val = val.val
nd = self.find(val)
if nd is None: return
self._delete(nd)
def _delete(self,nd):
y = None
if nd.left and nd.right:
y= self.getSuccessor(nd)
else:
y = nd
py = y.parent
x = y.left if y.left else y.right
if py is None:
self.setRoot(x)
else:
py.setChild(x,py.left is y)
if y != nd:
self.copyNode(y,nd)
if self.checkBlack(y): self.fixUpDel(py,x)
def fixUpDel(self,prt,chd):
''' adjust colors and rotate '''
while self.root != chd and self.checkBlack(chd):
isLeft =prt.left is chd
brother = prt.getChild(not isLeft)
# brother is black
lb = self.checkBlack(brother.getChild(isLeft))
rb = self.checkBlack(brother.getChild(not isLeft))
if not self.checkBlack(brother):
# case 1: brother is red. converted to case 2,3,4
self.setBlack(prt,False)
self.setBlack(brother,True)
self.rotate(prt,brother)
elif lb and rb:
# case 2: brother is black and two kids are black.
# conveted to the begin case
self.setBlack(brother,False)
chd = prt
prt= chd.parent
else:
if rb:
# case 3: brother is black and left kid is red and right child is black
# rotate bro to make g w wl wr in one line
# uncle's son is nephew, and niece for uncle's daughter
nephew = brother.getChild(isLeft)
self.setBlack(nephew,True)
self.setBlack(brother,False)
# brother (not isLeft) rotate
self.rotate(brother,nephew)
brother = nephew
# case 4: brother is black and right child is red
brother.isBlack = prt.isBlack
self.setBlack(prt,True)
self.setBlack(brother.getChild(not isLeft),True)
self.rotate(prt,brother)
chd = self.root
self.setBlack(chd,True)
def sort(self,reverse = False): def sort(self,reverse = False):
''' return a generator of sorted data''' ''' return a generator of sorted data'''
def inOrder(root): def inOrder(root):
@ -77,184 +222,6 @@ class redBlackTree:
else: else:
yield from inOrder(root.right) yield from inOrder(root.right)
yield from inOrder(self.root) yield from inOrder(self.root)
def getParent(self,chd):
'''note that use is to find real node when different nodes have euqiv val'''
if self.root is chd:return None
nd = self.root
while nd:
if nd>chd and nd.left is not None:
if nd.left is chd: return nd
else: nd = nd.left
elif nd<chd and nd.right is not None:
if nd.right is chd: return nd
else: nd = nd.right
def find(self,val):
nd = self.root
while nd:
if nd.val ==val:
return nd
elif nd.val>val:
nd = nd.left
else:
nd = nd.right
def getSuccessor(self,nd):
if nd:
if nd.right:
nd = nd.right
while nd.left:
nd = nd.left
return nd
else:return self.getParent(nd)
def transferParent(self,origin,new):
if origin is self.root:
self.root = new
else:
prt = self.getParent(origin)
prt.setChild(new, prt.left is origin)
def insert(self,nd):
if not isinstance(nd,node):
nd = node(nd)
elif nd.isBlack: nd.isBlack = False
if self.root is None:
self.root = nd
self.root.isBlack = True
else:
parent = self.root
while parent:
if parent == nd : return None
if parent>nd:
if parent.left :
parent = parent.left
else:
parent.left = nd
break
else:
if parent.right:
parent = parent.right
else:
parent.right = nd
break
self.fixUpInsert(parent,nd)
def fixUpInsert(self,parent,nd):
''' adjust color and level, there are two red nodes: the new one and its parent'''
while not self.checkBlack(parent):
grand = self.getParent(parent)
isLeftPrt = grand.left is parent
uncle = grand.getChild(not isLeftPrt)
if not self.checkBlack(uncle):
# case 1: new node's uncle is red
self.setBlack(grand, False)
self.setBlack(grand.left, True)
self.setBlack(grand.right, True)
nd = grand
parent = self.getParent(nd)
else:
# case 2: new node's uncle is black(including nil leaf)
isLeftNode = parent.left is nd
if isLeftNode ^ isLeftPrt:
# case 2.1 the new node is inserted in left-right or right-left form
# grand grand
# parent or parent
# nd nd
parent.setChild(nd.getChild(isLeftPrt),not isLeftPrt)
nd.setChild(parent,isLeftPrt)
grand.setChild(nd,isLeftPrt)
nd,parent = parent,nd
# case 2.2 the new node is inserted in left-left or right-right form
# grand grand
# parent or parent
# nd nd
grand.setChild(parent.getChild(not isLeftPrt),isLeftPrt)
parent.setChild(grand,not isLeftPrt)
self.setBlack(grand, False)
self.setBlack(parent, True)
self.transferParent(grand,parent)
self.setBlack(self.root,True)
def copyNode(self,src,des):
'''when deleting a node which has two kids,
copy its succesor's data to his position
data exclude left, right , isBlack
'''
des.val = src.val
def delete(self,nd):
'''delete node in a binary search tree'''
if not isinstance(nd,node):
nd = self.find(nd)
if nd is None: return
y = None
if nd.left and nd.right:
y= self.getSuccessor(nd)
else:
y = nd
py = self.getParent(y)
x = y.left if y.left else y.right
if py is None:
self.root = x
elif y is py.left:
py.left = x
else:
py.right = x
if y != nd:
self.copyNode(y,nd)
if self.checkBlack(y): self.fixUpDel(py,x)
def fixUpDel(self,prt,chd):
''' adjust colors and rotate '''
while self.root != chd and self.checkBlack(chd):
isLeft = prt.left is chd
brother = prt.getChild(not isLeft)
# brother is black
lb = self.checkBlack(brother.getChild(isLeft))
rb = self.checkBlack(brother.getChild(not isLeft))
if not self.checkBlack(brother):
# case 1: brother is red. converted to case 2,3,4
# prt (isLeft) rotate
prt.setChild(brother.getChild(isLeft), not isLeft)
brother.setChild(prt, isLeft)
self.setBlack(prt,False)
self.setBlack(brother,True)
self.transferParent(prt,brother)
elif lb and rb:
# case 2: brother is black and two kids are black.
# conveted to the begin case
self.setBlack(brother,False)
chd = prt
prt = self.getParent(chd)
else:
if rb:
# case 3: brother is black and left kid is red and right child is black
# uncle's son is nephew, and niece for uncle's daughter
nephew = brother.getChild(isLeft)
self.setBlack(nephew,True)
self.setBlack(brother,False)
# brother (not isLeft) rotate
prt.setChild(nephew,not isLeft)
brother.setChild(nephew.getChild(not isLeft),isLeft)
nephew.setChild(brother, not isLeft)
brother = nephew
# case 4: brother is black and right child is red
brother.isBlack = prt.isBlack
self.setBlack(prt,True)
self.setBlack(brother.getChild(not isLeft),True)
# prt left rotate
prt.setChild(brother.getChild(isLeft),not isLeft)
brother.setChild(prt,isLeft)
self.transferParent(prt,brother)
chd = self.root
self.setBlack(chd,True)
def display(self): def display(self):
def getHeight(nd): def getHeight(nd):
@ -280,7 +247,7 @@ class redBlackTree:
lst +=[None,None] lst +=[None,None]
return level return level
def addBlank(lines): def addBlank(lines):
width = 5 width = 1+len(str(self.root))
sep = ' '*width sep = ' '*width
n = len(lines) n = len(lines)
for i,oneline in enumerate(lines): for i,oneline in enumerate(lines):
@ -295,10 +262,10 @@ class redBlackTree:
lines = levelVisit(self.root) lines = levelVisit(self.root)
lines = addBlank(lines) lines = addBlank(lines)
li = [''.join(line) for line in lines] li = [''.join(line) for line in lines]
li.insert(0,'red-black-tree'.rjust(48,'-') + '-'*33) length = 10 if li==[] else max(len(i) for i in li)//2
li.append('end'.rjust(42,'-')+'-'*39+'\n') begin ='\n'+ 'red-black-tree'.rjust(length+14,'-') + '-'*(length)
return '\n'.join(li) end = '-'*(length*2+14)+'\n'
return '\n'.join([begin,*li,end])
def __str__(self): def __str__(self):
return self.display() return self.display()
@ -318,34 +285,35 @@ def buildTree(n=10,nums=None,visitor=None):
rbtree = redBlackTree() rbtree = redBlackTree()
print(f'build a red-black tree using {nums}') print(f'build a red-black tree using {nums}')
for i in nums: for i in nums:
rbtree.insert(i) rbtree.insert(node(i))
if visitor: if visitor:
visitor(rbtree) visitor(rbtree,i)
return rbtree,nums return rbtree,nums
def testInsert(): def testInsert(nums=None):
def visitor(t): def visitor(t,val):
print('inserting', val)
print(t) print(t)
rbtree,nums = buildTree(visitor = visitor) rbtree,nums = buildTree(visitor = visitor,nums=nums)
print('-'*5+ 'in-order visit' + '-'*5) print('-'*5+ 'in-order visit' + '-'*5)
for i,j in enumerate(rbtree.sort()): for i,j in enumerate(rbtree.sort()):
print(f'{i+1}: {j}') print(f'{i+1}: {j}')
def testSuc(): def testSuc(nums=None):
rbtree,nums = buildTree() rbtree,nums = buildTree(nums=nums)
for i in rbtree.sort(): for i in rbtree.sort():
print(f'{i}\'s suc is {rbtree.getSuccessor(i)}') print(f'{i}\'s suc is {rbtree.getSuccessor(i)}')
def testDelete(): def testDelete(nums=None):
#nums = [2,3,3,2,6,7,2,1]
nums = None
rbtree,nums = buildTree(nums = nums) rbtree,nums = buildTree(nums = nums)
print(rbtree) print(rbtree)
for i in nums: for i in sorted(nums):
print(f'deleting {i}') print(f'deleting {i}')
rbtree.delete(i) rbtree.delete(i)
print(rbtree) print(rbtree)
if __name__=='__main__': if __name__=='__main__':
#testSuc() lst =[45, 30, 64, 36, 95, 38, 76, 34, 50, 1]
#testInsert() lst = [0,3,5,6,26,25,8,19,15,16,17]
#testSuc(lst)
#testInsert(lst)
testDelete() testDelete()

View File

@ -0,0 +1,339 @@
''' mbinary
#########################################################################
# File : redBlackTree.py
# Author: mbinary
# Mail: zhuheqin1@gmail.com
# Blog: https://mbinary.coding.me
# Github: https://github.com/mbinary
# Created Time: 2018-07-14 16:15
# Description:
#########################################################################
'''
from functools import total_ordering
from random import randint, shuffle
@total_ordering
class node:
def __init__(self,val,left=None,right=None,isBlack=False):
self.val =val
self.left = left
self.right = right
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):
if isLeft: self.left = nd
else: self.right = nd
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}'
def __repr__(self):
return f'node({self.val},isBlack={self.isBlack})'
class redBlackTree:
def __init__(self,unique=False):
'''if unique is True, all node'vals are unique, else there may be equal vals'''
self.root = None
self.unique = unique
@staticmethod
def checkBlack(nd):
return nd is None or nd.isBlack
@staticmethod
def setBlack(nd,isBlack):
if nd is not None:
if isBlack is None or isBlack:
nd.isBlack = True
else:nd.isBlack = False
def getParent(self,chd):
'''note that use is to find real node when different nodes have euqiv val'''
if self.root is chd:return None
nd = self.root
while nd:
if nd>chd and nd.left is not None:
if nd.left is chd: return nd
else: nd = nd.left
elif nd<chd and nd.right is not None:
if nd.right is chd: return nd
else: nd = nd.right
def find(self,val):
nd = self.root
while nd:
if nd.val ==val:
return nd
else:
nd = nd.getChild(nd.val>val)
def getSuccessor(self,nd):
if nd:
if nd.right:
nd = nd.right
while nd.left:
nd = nd.left
return nd
else:return self.getParent(nd)
def setRoot(self,nd):
if nd is not None: nd.parent=None
self.root= nd
def transferParent(self,origin,new):
if origin is self.root:
self.root = new
else:
prt = self.getParent(origin)
prt.setChild(new, prt.left is origin)
def rotate(self,prt,chd,direction):
'''rotate prt, and return new prt, namyly the original chd'''
prt.setChild(chd.getChild(direction), not direction)
chd.setChild(prt,direction)
return chd
def insert(self,nd):
if nd.isBlack: nd.isBlack = False
if self.root is None:
self.setRoot(nd)
self.root.isBlack = True
else:
parent = self.root
while parent:
if parent == nd : return None
isLeft = parent > nd
chd = parent.getChild(isLeft)
if chd is None:
parent.setChild(nd,isLeft)
break
else:
parent = chd
self.fixUpInsert(parent,nd)
def fixUpInsert(self,parent,nd):
''' adjust color and level, there are two red nodes: the new one and its parent'''
while not self.checkBlack(parent):
grand = self.getParent(parent)
isLeftPrt = grand.left is parent
uncle = grand.getChild(not isLeftPrt)
if not self.checkBlack(uncle):
# case 1: new node's uncle is red
self.setBlack(grand, False)
self.setBlack(grand.left, True)
self.setBlack(grand.right, True)
nd = grand
parent = self.getParent(nd)
else:
# case 2: new node's uncle is black(including nil leaf)
isLeftNode = parent.left is nd
if isLeftNode ^ isLeftPrt:
# case 2.1 the new node is inserted in left-right or right-left form
# grand grand
# parent or parent
# nd nd
self.rotate(parent,nd,isLeftPrt) #parent rotate
grand.setChild(nd,isLeftPrt)
nd,parent = parent,nd
# case 2.2 the new node is inserted in left-left or right-right form
# grand grand
# parent or parent
# nd nd
# grand rotate
self.rotate(grand,parent,not isLeftPrt)
self.setBlack(grand, False)
self.setBlack(parent, True)
self.transferParent(grand,parent)
self.setBlack(self.root,True)
def copyNode(self,src,des):
'''when deleting a node which has two kids,
copy its succesor's data to his position
data exclude left, right , isBlack
'''
des.val = src.val
def delete(self,val):
'''delete node in a binary search tree'''
if isinstance(val,node): val = val.val
nd = self.find(val)
if nd is None: return
y = None
if nd.left and nd.right:
y= self.getSuccessor(nd)
else:
y = nd
py = self.getParent(y)
x = y.left if y.left else y.right
if py is None:
self.root = x
else:
py.setChild(x,py.left is y)
if y != nd:
self.copyNode(y,nd)
if self.checkBlack(y): self.fixUpDel(py,x)
def fixUpDel(self,prt,chd):
''' adjust colors and rotate '''
while self.root != chd and self.checkBlack(chd):
isLeft = prt.left is chd
brother = prt.getChild(not isLeft)
# brother is black
lb = self.checkBlack(brother.getChild(isLeft))
rb = self.checkBlack(brother.getChild(not isLeft))
if not self.checkBlack(brother):
# case 1: brother is red. converted to case 2,3,4
# prt (isLeft) rotate
self.rotate(prt,brother,isLeft)
self.setBlack(prt,False)
self.setBlack(brother,True)
self.transferParent(prt,brother)
elif lb and rb:
# case 2: brother is black and two kids are black.
# conveted to the begin case
self.setBlack(brother,False)
chd = prt
prt = self.getParent(chd)
else:
if rb:
# case 3: brother is black and left kid is red and right child is black
# uncle's son is nephew, and niece for uncle's daughter
nephew = brother.getChild(isLeft)
self.setBlack(nephew,True)
self.setBlack(brother,False)
# brother (not isLeft) rotate
prt.setChild(nephew,not isLeft)
self.rotate(brother,nephew,not isLeft)
brother = nephew
# case 4: brother is black and right child is red
brother.isBlack = prt.isBlack
self.setBlack(prt,True)
self.setBlack(brother.getChild(not isLeft),True)
# prt left rotate
self.rotate(prt,brother,isLeft)
self.transferParent(prt,brother)
chd = self.root
self.setBlack(chd,True)
def sort(self,reverse = False):
''' return a generator of sorted data'''
def inOrder(root):
if root is None:return
if reverse:
yield from inOrder(root.right)
else:
yield from inOrder(root.left)
yield root
if reverse:
yield from inOrder(root.left)
else:
yield from inOrder(root.right)
yield from inOrder(self.root)
def display(self):
def getHeight(nd):
if nd is None:return 0
return max(getHeight(nd.left),getHeight(nd.right)) +1
def levelVisit(root):
from collections import deque
lst = deque([root])
level = []
h = getHeight(root)
ct = lv = 0
while 1:
ct+=1
nd = lst.popleft()
if ct >= 2**lv:
lv+=1
if lv>h:break
level.append([])
level[-1].append(str(nd))
if nd is not None:
lst += [nd.left,nd.right]
else:
lst +=[None,None]
return level
def addBlank(lines):
width = 5
sep = ' '*width
n = len(lines)
for i,oneline in enumerate(lines):
k = 2**(n-i) -1
new = [sep*((k-1)//2)]
for s in oneline:
new.append(s.ljust(width))
new.append(sep*k)
lines[i] = new
return lines
lines = levelVisit(self.root)
lines = addBlank(lines)
li = [''.join(line) for line in lines]
li.insert(0,'red-black-tree'.rjust(48,'-') + '-'*33)
li.append('end'.rjust(42,'-')+'-'*39+'\n')
return '\n'.join(li)
def __str__(self):
return self.display()
def genNum(n =10):
nums =[]
for i in range(n):
while 1:
d = randint(0,100)
if d not in nums:
nums.append(d)
break
return nums
def buildTree(n=10,nums=None,visitor=None):
if nums is None or nums ==[]: nums = genNum(n)
rbtree = redBlackTree()
print(f'build a red-black tree using {nums}')
for i in nums:
rbtree.insert(node(i))
if visitor:
visitor(rbtree,i)
return rbtree,nums
def testInsert(nums=None):
def visitor(t,val):
print('inserting',val)
print(t)
rbtree,nums = buildTree(visitor = visitor,nums=nums)
print('-'*5+ 'in-order visit' + '-'*5)
for i,j in enumerate(rbtree.sort()):
print(f'{i+1}: {j}')
def testSuc(nums=None):
rbtree,nums = buildTree(nums=nums)
print(rbtree)
for i in rbtree.sort():
print(f'{i}\'s suc is {rbtree.getSuccessor(i)}')
def testDelete(nums=None):
rbtree,nums = buildTree(nums = nums)
print(rbtree)
for i in nums:
print(f'deleting {i}')
rbtree.delete(i)
print(rbtree)
if __name__=='__main__':
#lst = [41,38,31,12,19,8]
#lst.sort()
lst = None
lst =[45, 30, 64, 36, 95, 38, 76, 34, 50, 1]
testSuc()
testInsert(lst)
testDelete()

View File

@ -0,0 +1,124 @@
from random import randint
from time import time
from functools import total_ordering
@total_ordering
class point:
def __init__(self,x,y):
self.x=x
self.y=y
def __neg__(self):
return pont(-self.x, -self.y)
def __len__(self):
return self.norm(2)
def __lt__(self,p):
return self.x<p.x or (self.x==p.x and self.y<p.y)
def __eq__(self,p):
return self.x==p.x and self.y == p.y
def __hash__(self):
return hash((self.x,self.y))
def __repr__(self):
return 'point({},{})'.format(self.x,self.y)
def __str__(self):
return self.__repr__()
def norm(self,n=2):
if n<=0: return max(abs(self.x),abs(self.y))
return (abs(self.x)**n+abs(self.y)**n)**(1/n)
def distance(self,p):
return ((self.x-p.x)**2+(self.y-p.y)**2)**0.5
def minDistance_n2(points):
n = len(points)
if n<=1: return 0
p,q=points[:2]
minD = points[0].distance(points[1])
for i in range(n-1):
for j in range(i+1,n):
d = points[i].distance(points[j])
if d<minD:
minD = d
p = points[i]
q= points[j]
return minD, p,q
def findif(points, f,reverse = False):
n = len(points)
rg = range(n-1,-1,-1) if reverse else range(n)
for i in rg:
if not f(points[i]):
return points[i+1:] if reverse else points[:i]
return points.copy() # note that don't return exactly points, return a copy one
def floatEql(f1,f2,epsilon=1e-6):
return abs(f1-f2)<epsilon
def minDistance_nlogn(n_points):
def _min(pts):
n = len(pts)
if n==2: return pts[0].distance(pts[1]) , pts[0],pts[1]
if n==3:
minD = pts[0].distance(pts[1])
p,q = pts[0],pts[1]
d2 = pts[2].distance(pts[1])
if minD>d2:
minD = d2
p,q = pts[1], pts[2]
d2 = pts[0].distance(pts[2])
if minD>d2: return d2, pts[0],pts[2]
else : return minD, p,q
n2 = n//2
mid = (pts[n2].x +pts[n2-1].x)/2
s1 = pts[:n2]
s2 = pts[n2:]
minD ,p,q = _min(s1)
d2, p2, q2 = _min(s2)
#print('\n\n',minD,p,q,s1)
#print(d2,p2,q2,s2)
if minD> d2:
minD,p,q = d2, p2, q2
linePoints = findif(s1,lambda pt:floatEql(pt.x,mid),reverse=True)
linePoints += findif(s2,lambda pt:floatEql(pt.x,mid))
n = len(linePoints)
if n>1:
for i in range(1,n):
dis = linePoints[i].y -linePoints[i-1].y
if dis<minD:
minD = dis
p,q = linePoints[i-1], linePoints[i]
leftPoints = findif(s1,lambda pt:pt.x>= mid-minD,reverse=True)
rightPoints = findif(s2,lambda pt:pt.x<= mid+minD)
for lp in leftPoints:
y1,y2 = lp.y-minD, lp.y+minD
for rp in rightPoints:
if y1< rp.y <y2:
dis = lp.distance(rp)
if dis< minD:
minD = dis
p,q = lp,rp
return minD, p,q
return _min(sorted(n_points))
def test(f=minDistance_n2):
print('\ntest : ', f.__name__)
begin = time()
minD, p, q = f(points)
print('time : {:.6f} s'.format(time()-begin))
print('result: {:.2f} {} {}\n'.format(minD, p,q))
def genData(n,unique=True):
if unique:
points = set()
for i in range(n):
points.add(point(randint(1,1000),randint(1,1000)))
return list(points)
else:return [point(randint(1,1000),randint(1,1000)) for i in range(n)]
if __name__ =='__main__':
n = 10000
points = genData(n, unique=True)
print('min distance of {} points'.format(n))
#print(sorted(points))
test(minDistance_n2)
test(minDistance_nlogn)

View File

@ -37,7 +37,7 @@ description:
<a id="markdown-1-关键字" name="1-关键字"></a> <a id="markdown-1-关键字" name="1-关键字"></a>
# 1. 关键字 # 1. 关键字
由于关键字是用来索引数据的, 所以要求它不能变动(如果变动,实际上就是一个新的关键字插入了), 在python 中表现为 imutable. 常为字符串. 由于关键字是用来索引数据的, 所以要求它不能变动(如果变动,实际上就是一个新的关键字插入了), 在python 中表现为 immutable. 常为字符串.
<a id="markdown-2-映射" name="2-映射"></a> <a id="markdown-2-映射" name="2-映射"></a>
# 2. 映射 # 2. 映射

View File

@ -7,7 +7,6 @@ keywords:
mathjax: true mathjax: true
description: description:
--- ---
<!-- TOC --> <!-- TOC -->
- [1. 定义与性质](#1-定义与性质) - [1. 定义与性质](#1-定义与性质)
@ -47,7 +46,6 @@ description:
* right:pointer to right child * right:pointer to right child
* p: pointer to nil leaf * p: pointer to nil leaf
<a id="markdown-12-红黑性质" name="12-红黑性质"></a> <a id="markdown-12-红黑性质" name="12-红黑性质"></a>
## 1.2. 红黑性质 ## 1.2. 红黑性质
满足下面的 `红黑性质` 的二叉查找树就是红黑树: 满足下面的 `红黑性质` 的二叉查找树就是红黑树:
@ -57,7 +55,6 @@ description:
* 红结点的孩子是黑 * 红结点的孩子是黑
* 从每个结点出发,通过子孙到达叶子结点的各条路径上 黑结点数相等 * 从每个结点出发,通过子孙到达叶子结点的各条路径上 黑结点数相等
如,叶子结点 是 nil, 即不存储任何东西, 为了编程方便,相对的,存有数据的结点称为内结点 如,叶子结点 是 nil, 即不存储任何东西, 为了编程方便,相对的,存有数据的结点称为内结点
![](https://upload-images.jianshu.io/upload_images/7130568-95927d3ca6cc524d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) ![](https://upload-images.jianshu.io/upload_images/7130568-95927d3ca6cc524d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
@ -99,7 +96,6 @@ $$n \geqslant 2^{h_b(x)} -1 \geqslant 2^{\frac{h}{2}} -1$$
* 然后将新结点的 左右孩子设为 nil , 颜色设为红色 * 然后将新结点的 左右孩子设为 nil , 颜色设为红色
* 最后再进行颜色调整以及旋转(维持红黑性质) * 最后再进行颜色调整以及旋转(维持红黑性质)
这是算法导论[^1]上的算法 这是算法导论[^1]上的算法
```python ```python
RB-INSERT(T, z) RB-INSERT(T, z)
@ -198,7 +194,11 @@ RB-INSERT(T, z)
### 3.2.3. 总体解决方案 ### 3.2.3. 总体解决方案
我最开始也没有弄清楚, 有点绕晕的感觉, 后来仔细读了书上伪代码, 然后才发现就是一个状态机, 画出来就一目了然了. 我最开始也没有弄清楚, 有点绕晕的感觉, 后来仔细读了书上伪代码, 然后才发现就是一个状态机, 画出来就一目了然了.
![](https://upload-images.jianshu.io/upload_images/7130568-bd3a0ffca482eb73.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) ![](https://upload-images.jianshu.io/upload_images/7130568-53dd71e22a315242.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
现在算是知其然了, 那么怎样知其所以然呢? 即 为什么要分类这三个 case, 不重不漏了吗? 现在算是知其然了, 那么怎样知其所以然呢? 即 为什么要分类这三个 case, 不重不漏了吗?
@ -287,12 +287,10 @@ color[root[T]] ← BLACK
* 当 z 孩子全是 nil (y==z): 直接让其双亲对应的孩子为 nil * 当 z 孩子全是 nil (y==z): 直接让其双亲对应的孩子为 nil
* 当 z 只有一个非 nil 孩子 x (y==z): * 当 z 只有一个非 nil 孩子 x (y==z):
1. 如果 z 为根, 则让 x 为根. 1. 如果 z 为根, 则让 x 为根.
2. 让 y 的双亲连接到 x 2. 让 y 的双亲连接到 x
* 当 z 有两个非nil孩子(y!=z): 复制其后继 y 的内容到 z (除了指针,颜色) , 将其后继 y 的孩子(最多只有一个 非 nil ,不然就不是后继了)连接到其后继的双亲, 删除 其后继y, * 当 z 有两个非nil孩子(y!=z): 复制其后继 y 的内容到 z (除了指针,颜色) , 将其后继 y 的孩子(最多只有一个 非 nil ,不然就不是后继了)连接到其后继的双亲, 删除 其后继y,
即[^3] 如果要删除有两个孩子的结点 z , 则找到它的后继y(前趋同理), 可以推断 y 一定没有左孩子, 右孩子可能有,可能没有. 也就是最多一个孩子. 即[^3] 如果要删除有两个孩子的结点 z , 则找到它的后继y(前趋同理), 可以推断 y 一定没有左孩子, 右孩子可能有,可能没有. 也就是最多一个孩子.
所以将 y 的值复制到 x 位置, 现在相当于删除 y 处的结点. 所以将 y 的值复制到 x 位置, 现在相当于删除 y 处的结点.
这样就化为 删除的结点最多一个孩子的情况. 这样就化为 删除的结点最多一个孩子的情况.
@ -321,7 +319,6 @@ color[root[T]] ← BLACK
* x 指向根,这时可以简单地消除额外的黑色 * x 指向根,这时可以简单地消除额外的黑色
* 颜色修改与旋转 * 颜色修改与旋转
在 while 中, x 总是指向具有双重黑色的那个非根结点, 在第 2 行中要判断 x 是其双亲的左右孩子 在 while 中, x 总是指向具有双重黑色的那个非根结点, 在第 2 行中要判断 x 是其双亲的左右孩子
w 表示 x 的相抵. w 不能为 nil(因为 x 是双重黑色) w 表示 x 的相抵. w 不能为 nil(因为 x 是双重黑色)
@ -330,20 +327,19 @@ w 表示 x 的相抵. w 不能为 nil(因为 x 是双重黑色)
* x 的兄弟 w 是红色的 * x 的兄弟 w 是红色的
![](https://upload-images.jianshu.io/upload_images/7130568-cd139202bdc5406f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) ![](https://upload-images.jianshu.io/upload_images/7130568-cd139202bdc5406f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
* x 的兄弟 w 是黑色的, w的两个孩子都是黑色的 * x 的兄弟 w 是黑色的, w的两个孩子都是黑色的
* x 的兄弟 w 是黑色的, w 的左孩子是红,右孩子是黑 * x 的兄弟 w 是黑色的, w 的左孩子是红,右孩子是黑
* x 的兄弟 w 是黑色的, w 的孩子是红色的 * x 的兄弟 w 是黑色的, w 的孩子是红色的
>>注意上面都是先考虑的左边, 右边可以对称地处理. >>注意上面都是先考虑的左边, 右边可以对称地处理.
同插入一样, 为了便于理解, 可以作出状态机. 同插入一样, 为了便于理解, 可以作出状态机.
而且这些情形都是归纳化简了的, 你也可以枚举列出基本的全部情形. 而且这些情形都是归纳化简了的, 你也可以枚举列出基本的全部情形.
![](https://upload-images.jianshu.io/upload_images/7130568-d6e8a332afade8d5.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
![](https://upload-images.jianshu.io/upload_images/7130568-005e2a7d55860559.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
<a id="markdown-5-数据结构的扩张" name="5-数据结构的扩张"></a> <a id="markdown-5-数据结构的扩张" name="5-数据结构的扩张"></a>
# 5. 数据结构的扩张 # 5. 数据结构的扩张
@ -374,28 +370,23 @@ def find(root,i):
<a id="markdown-6-python-代码" name="6-python-代码"></a> <a id="markdown-6-python-代码" name="6-python-代码"></a>
# 6. python 代码 # 6. python 代码
**[github地址](https://github.com/mbinary/algorithm-and-data-structure.git)** **[github地址](https://github.com/mbinary/algorithm-in-python.git)**
我的代码有两点不同 我用了 setChild, getChild 来简化代码量, 其他的基本上是按照算法导论上的伪代码提到的case 来实现的. 然后display 只是测试的时候,为了方便调试而层序遍历打印出来
* 用了 setChild, getChild 来简化代码量
* 每个结点没有上面的 p 域, 即指向 nil leaf的,我直接让 left, right 为 `None`, 然后定义了两个函数 `setBlack`, `checkBlack` 来操作 颜色数据 isBlack(当为 True 时代表黑色,否则为红). 如果为 None, 这两个函数也能正确的处理.可以直接见代码
其他的基本上是按照算法导论上的伪代码提到的case 来实现的. 然后display 只是测试的时候,为了方便调试而层序遍历打印出来
效果如下 效果如下
![](https://upload-images.jianshu.io/upload_images/7130568-721e18cc44dec604.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) ![](https://upload-images.jianshu.io/upload_images/7130568-721e18cc44dec604.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
```python ```python
''' ''' mbinary
######################################################################### #########################################################################
# File : redBlackTree.py # File : redBlackTree.py
# Author: mbinary # Author: mbinary
# Mail: zhuheqin1@gmail.com # Mail: zhuheqin1@gmail.com
# Blog: https://mbinary.coding.me # Blog: https://mbinary.coding.me
# Github: https://github.com/mbinary # Github: https://github.com/mbinary
# Created Time: 2018-07-12 20:34 # Created Time: 2018-07-14 16:15
# Description: # Description:
######################################################################### #########################################################################
''' '''
from functools import total_ordering from functools import total_ordering
@ -407,14 +398,17 @@ class node:
self.val =val self.val =val
self.left = left self.left = left
self.right = right self.right = right
self.parent= None
self.isBlack = isBlack self.isBlack = isBlack
def __lt__(self,nd): def __lt__(self,nd):
return self.val < nd.val return self.val < nd.val
def __eq__(self,nd): def __eq__(self,nd):
return nd is not None and self.val == nd.val return nd is not None and self.val == nd.val
def setChild(self,nd,isLeft = True): def setChild(self,nd,isLeft):
if isLeft: self.left = nd if isLeft: self.left = nd
else: self.right = nd else: self.right = nd
if nd is not None: nd.parent = self
def getChild(self,isLeft): def getChild(self,isLeft):
if isLeft: return self.left if isLeft: return self.left
else: return self.right else: return self.right
@ -422,7 +416,8 @@ class node:
return self.val is not None return self.val is not None
def __str__(self): def __str__(self):
color = 'B' if self.isBlack else 'R' color = 'B' if self.isBlack else 'R'
return f'{color}-{self.val:}' val = '-' if self.parent==None else self.parent.val
return f'{color}-{self.val}'
def __repr__(self): def __repr__(self):
return f'node({self.val},isBlack={self.isBlack})' return f'node({self.val},isBlack={self.isBlack})'
class redBlackTree: class redBlackTree:
@ -440,6 +435,159 @@ class redBlackTree:
if isBlack is None or isBlack: if isBlack is None or isBlack:
nd.isBlack = True nd.isBlack = True
else:nd.isBlack = False else:nd.isBlack = False
def setRoot(self,nd):
if nd is not None: nd.parent=None
self.root= nd
def find(self,val):
nd = self.root
while nd:
if nd.val ==val:
return nd
else:
nd = nd.getChild(nd.val>val)
def getSuccessor(self,nd):
if nd:
if nd.right:
nd = nd.right
while nd.left:
nd = nd.left
return nd
else:
while nd.parent is not None and nd.parent.right is nd:
nd = nd.parent
return None if nd is self.root else nd.parent
def rotate(self,prt,chd):
'''rotate prt with the center of chd'''
if self.root is prt:
self.setRoot(chd)
else:
prt.parent.setChild(chd, prt.parent.left is prt)
isLeftChd = prt.left is chd
prt.setChild(chd.getChild(not isLeftChd), isLeftChd)
chd.setChild(prt,not isLeftChd)
def insert(self,nd):
if nd.isBlack: nd.isBlack = False
if self.root is None:
self.setRoot(nd)
self.root.isBlack = True
else:
parent = self.root
while parent:
if parent == nd : return None
isLeft = parent > nd
chd = parent.getChild(isLeft)
if chd is None:
parent.setChild(nd,isLeft)
break
else:
parent = chd
self.fixUpInsert(parent,nd)
def fixUpInsert(self,parent,nd):
''' adjust color and level, there are two red nodes: the new one and its parent'''
while not self.checkBlack(parent):
grand = parent.parent
isLeftPrt = grand.left is parent
uncle = grand.getChild(not isLeftPrt)
if not self.checkBlack(uncle):
# case 1: new node's uncle is red
self.setBlack(grand, False)
self.setBlack(grand.left, True)
self.setBlack(grand.right, True)
nd = grand
parent = nd.parent
else:
# case 2: new node's uncle is black(including nil leaf)
isLeftNode = parent.left is nd
if isLeftNode ^ isLeftPrt:
# case 2.1 the new node is inserted in left-right or right-left form
# grand grand
# parent or parent
# nd nd
self.rotate(parent,nd) #parent rotate
nd,parent = parent,nd
# case 3 (case 2.2) the new node is inserted in left-left or right-right form
# grand grand
# parent or parent
# nd nd
self.setBlack(grand, False)
self.setBlack(parent, True)
self.rotate(grand,parent)
self.setBlack(self.root,True)
def copyNode(self,src,des):
'''when deleting a node which has two kids,
copy its succesor's data to his position
data exclude left, right , isBlack
'''
des.val = src.val
def delete(self,val):
'''delete node in a binary search tree'''
if isinstance(val,node): val = val.val
nd = self.find(val)
if nd is None: return
self._delete(nd)
def _delete(self,nd):
y = None
if nd.left and nd.right:
y= self.getSuccessor(nd)
else:
y = nd
py = y.parent
x = y.left if y.left else y.right
if py is None:
self.setRoot(x)
else:
py.setChild(x,py.left is y)
if y != nd:
self.copyNode(y,nd)
if self.checkBlack(y): self.fixUpDel(py,x)
def fixUpDel(self,prt,chd):
''' adjust colors and rotate '''
while self.root != chd and self.checkBlack(chd):
isLeft =prt.left is chd
brother = prt.getChild(not isLeft)
# brother is black
lb = self.checkBlack(brother.getChild(isLeft))
rb = self.checkBlack(brother.getChild(not isLeft))
if not self.checkBlack(brother):
# case 1: brother is red. converted to case 2,3,4
self.setBlack(prt,False)
self.setBlack(brother,True)
self.rotate(prt,brother)
elif lb and rb:
# case 2: brother is black and two kids are black.
# conveted to the begin case
self.setBlack(brother,False)
chd = prt
prt= chd.parent
else:
if rb:
# case 3: brother is black and left kid is red and right child is black
# rotate bro to make g w wl wr in one line
# uncle's son is nephew, and niece for uncle's daughter
nephew = brother.getChild(isLeft)
self.setBlack(nephew,True)
self.setBlack(brother,False)
# brother (not isLeft) rotate
self.rotate(brother,nephew)
brother = nephew
# case 4: brother is black and right child is red
brother.isBlack = prt.isBlack
self.setBlack(prt,True)
self.setBlack(brother.getChild(not isLeft),True)
self.rotate(prt,brother)
chd = self.root
self.setBlack(chd,True)
def sort(self,reverse = False): def sort(self,reverse = False):
''' return a generator of sorted data''' ''' return a generator of sorted data'''
def inOrder(root): def inOrder(root):
@ -454,184 +602,6 @@ class redBlackTree:
else: else:
yield from inOrder(root.right) yield from inOrder(root.right)
yield from inOrder(self.root) yield from inOrder(self.root)
def getParent(self,chd):
'''note that use is to find real node when different nodes have euqiv val'''
if self.root is chd:return None
nd = self.root
while nd:
if nd>chd and nd.left is not None:
if nd.left is chd: return nd
else: nd = nd.left
elif nd<chd and nd.right is not None:
if nd.right is chd: return nd
else: nd = nd.right
def find(self,val):
nd = self.root
while nd:
if nd.val ==val:
return nd
elif nd.val>val:
nd = nd.left
else:
nd = nd.right
def getSuccessor(self,nd):
if nd:
if nd.right:
nd = nd.right
while nd.left:
nd = nd.left
return nd
else:return self.getParent(nd)
def transferParent(self,origin,new):
if origin is self.root:
self.root = new
else:
prt = self.getParent(origin)
prt.setChild(new, prt.left is origin)
def insert(self,nd):
if not isinstance(nd,node):
nd = node(nd)
elif nd.isBlack: nd.isBlack = False
if self.root is None:
self.root = nd
self.root.isBlack = True
else:
parent = self.root
while parent:
if parent == nd : return None
if parent>nd:
if parent.left :
parent = parent.left
else:
parent.left = nd
break
else:
if parent.right:
parent = parent.right
else:
parent.right = nd
break
self.fixUpInsert(parent,nd)
def fixUpInsert(self,parent,nd):
''' adjust color and level, there are two red nodes: the new one and its parent'''
while not self.checkBlack(parent):
grand = self.getParent(parent)
isLeftPrt = grand.left is parent
uncle = grand.getChild(not isLeftPrt)
if not self.checkBlack(uncle):
# case 1: new node's uncle is red
self.setBlack(grand, False)
self.setBlack(grand.left, True)
self.setBlack(grand.right, True)
nd = grand
parent = self.getParent(nd)
else:
# case 2: new node's uncle is black(including nil leaf)
isLeftNode = parent.left is nd
if isLeftNode ^ isLeftPrt:
# case 2.1 the new node is inserted in left-right or right-left form
# grand grand
# parent or parent
# nd nd
parent.setChild(nd.getChild(isLeftPrt),not isLeftPrt)
nd.setChild(parent,isLeftPrt)
grand.setChild(nd,isLeftPrt)
nd,parent = parent,nd
# case 2.2 the new node is inserted in left-left or right-right form
# grand grand
# parent or parent
# nd nd
grand.setChild(parent.getChild(not isLeftPrt),isLeftPrt)
parent.setChild(grand,not isLeftPrt)
self.setBlack(grand, False)
self.setBlack(parent, True)
self.transferParent(grand,parent)
self.setBlack(self.root,True)
def copyNode(self,src,des):
'''when deleting a node which has two kids,
copy its succesor's data to his position
data exclude left, right , isBlack
'''
des.val = src.val
def delete(self,nd):
'''delete node in a binary search tree'''
if not isinstance(nd,node):
nd = self.find(nd)
if nd is None: return
y = None
if nd.left and nd.right:
y= self.getSuccessor(nd)
else:
y = nd
py = self.getParent(y)
x = y.left if y.left else y.right
if py is None:
self.root = x
elif y is py.left:
py.left = x
else:
py.right = x
if y != nd:
self.copyNode(y,nd)
if self.checkBlack(y): self.fixUpDel(py,x)
def fixUpDel(self,prt,chd):
''' adjust colors and rotate '''
while self.root != chd and self.checkBlack(chd):
isLeft = prt.left is chd
brother = prt.getChild(not isLeft)
# brother is black
lb = self.checkBlack(brother.getChild(isLeft))
rb = self.checkBlack(brother.getChild(not isLeft))
if not self.checkBlack(brother):
# case 1: brother is red. converted to case 2,3,4
# prt (isLeft) rotate
prt.setChild(brother.getChild(isLeft), not isLeft)
brother.setChild(prt, isLeft)
self.setBlack(prt,False)
self.setBlack(brother,True)
self.transferParent(prt,brother)
elif lb and rb:
# case 2: brother is black and two kids are black.
# conveted to the begin case
self.setBlack(brother,False)
chd = prt
prt = self.getParent(chd)
else:
if rb:
# case 3: brother is black and left kid is red and right child is black
# uncle's son is nephew, and niece for uncle's daughter
nephew = brother.getChild(isLeft)
self.setBlack(nephew,True)
self.setBlack(brother,False)
# brother (not isLeft) rotate
prt.setChild(nephew,not isLeft)
brother.setChild(nephew.getChild(not isLeft),isLeft)
nephew.setChild(brother, not isLeft)
brother = nephew
# case 4: brother is black and right child is red
brother.isBlack = prt.isBlack
self.setBlack(prt,True)
self.setBlack(brother.getChild(not isLeft),True)
# prt left rotate
prt.setChild(brother.getChild(isLeft),not isLeft)
brother.setChild(prt,isLeft)
self.transferParent(prt,brother)
chd = self.root
self.setBlack(chd,True)
def display(self): def display(self):
def getHeight(nd): def getHeight(nd):
@ -657,7 +627,7 @@ class redBlackTree:
lst +=[None,None] lst +=[None,None]
return level return level
def addBlank(lines): def addBlank(lines):
width = 5 width = 1+len(str(self.root))
sep = ' '*width sep = ' '*width
n = len(lines) n = len(lines)
for i,oneline in enumerate(lines): for i,oneline in enumerate(lines):
@ -672,15 +642,18 @@ class redBlackTree:
lines = levelVisit(self.root) lines = levelVisit(self.root)
lines = addBlank(lines) lines = addBlank(lines)
li = [''.join(line) for line in lines] li = [''.join(line) for line in lines]
li.insert(0,'red-black-tree'.rjust(48,'-') + '-'*33) length = 10 if li==[] else max(len(i) for i in li)//2
li.append('end'.rjust(42,'-')+'-'*39+'\n') begin ='\n'+ 'red-black-tree'.rjust(length+14,'-') + '-'*(length)
return '\n'.join(li) end = '-'*(length*2+14)+'\n'
return '\n'.join([begin,*li,end])
def __str__(self): def __str__(self):
return self.display() return self.display()
``` ```
测试代码 测试代码
```python ```python
def genNum(n =10): def genNum(n =10):
nums =[] nums =[]
for i in range(n): for i in range(n):
@ -696,36 +669,37 @@ def buildTree(n=10,nums=None,visitor=None):
rbtree = redBlackTree() rbtree = redBlackTree()
print(f'build a red-black tree using {nums}') print(f'build a red-black tree using {nums}')
for i in nums: for i in nums:
rbtree.insert(i) rbtree.insert(node(i))
if visitor: if visitor:
visitor(rbtree) visitor(rbtree,i)
return rbtree,nums return rbtree,nums
def testInsert(): def testInsert(nums=None):
def visitor(t): def visitor(t,val):
print('inserting', val)
print(t) print(t)
rbtree,nums = buildTree(visitor = visitor) rbtree,nums = buildTree(visitor = visitor,nums=nums)
print('-'*5+ 'in-order visit' + '-'*5) print('-'*5+ 'in-order visit' + '-'*5)
for i,j in enumerate(rbtree.sort()): for i,j in enumerate(rbtree.sort()):
print(f'{i+1}: {j}') print(f'{i+1}: {j}')
def testSuc(): def testSuc(nums=None):
rbtree,nums = buildTree() rbtree,nums = buildTree(nums=nums)
for i in rbtree.sort(): for i in rbtree.sort():
print(f'{i}\'s suc is {rbtree.getSuccessor(i)}') print(f'{i}\'s suc is {rbtree.getSuccessor(i)}')
def testDelete(): def testDelete(nums=None):
#nums = [2,3,3,2,6,7,2,1]
nums = None
rbtree,nums = buildTree(nums = nums) rbtree,nums = buildTree(nums = nums)
print(rbtree) print(rbtree)
for i in nums: for i in sorted(nums):
print(f'deleting {i}') print(f'deleting {i}')
rbtree.delete(i) rbtree.delete(i)
print(rbtree) print(rbtree)
if __name__=='__main__': if __name__=='__main__':
#testSuc() lst =[45, 30, 64, 36, 95, 38, 76, 34, 50, 1]
#testInsert() lst = [0,3,5,6,26,25,8,19,15,16,17]
#testSuc(lst)
#testInsert(lst)
testDelete() testDelete()
``` ```
@ -735,3 +709,4 @@ if __name__=='__main__':
[^2]: https://www.jianshu.com/p/a5514510f5b9?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation [^2]: https://www.jianshu.com/p/a5514510f5b9?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation
[^3]: https://www.jianshu.com/p/0b68b992f688?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation [^3]: https://www.jianshu.com/p/0b68b992f688?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

View File

@ -1,16 +0,0 @@
''' mbinary
#########################################################################
# File : matrix-multiply.py
# Author: mbinary
# Mail: zhuheqin1@gmail.com
# Blog: https://mbinary.coding.me
# Github: https://github.com/mbinary
# Created Time: 2018-08-24 21:24
# Description:
#########################################################################
'''
def adjustOrd(sizes):
''' adjust the chain-multiply of matrix, sizes=[row1,row2,..,rown,coln]'''
n = len(sizes)
if n<3: return

View File

@ -0,0 +1,32 @@
def matrixChainMultiply(seq):
'''matrix chain multiply, find the optimalest comb to multiply
eg ABCD, (AB)(CD), A((BC)D)
seq: sequence of matrix's scale, eg [A.row,A.col,B.col,C.col,D.col]
'''
print(seq)
n = len(seq)-1
mat = [[0]*n for i in range(n)]
mark = [[0]*n for i in range(n)]
for l in range(1,n):
for i in range(n):
j = i+l
if j>=n: continue
mat[i][j] = None
for k in range(i,j):
tmp = mat[i][k]+mat[k+1][j]+seq[i]*seq[k+1]*seq[j+1]
if mat[i][j] is None or mat[i][j]>tmp:
mark[i][j] = k
mat[i][j]= tmp
s= findSolution(mark,0,n-1)
print(s)
return mat[0][n-1]
def findSolution(mark,i,j):
if j==i: return 'M{}'.format(i+1)
if j-i==1: return 'M{} * M{}'.format(j,j+1)
k = mark[i][j]
return '('+findSolution(mark,i,k)+') * ('+findSolution(mark,k+1,j)+')'
if __name__=='__main__':
seq = [5,10,3,12,5,50,6]
res = matrixChainMultiply(seq)
print(res)

52
math/arrangement.c Normal file
View File

@ -0,0 +1,52 @@
#include<stdio.h>
void swap(int*arr,int i,int j)
{
int tmp;
tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
void nextArrangement(int *arr,int n)
{
if(arr[n-1]>arr[n-2]){
swap(arr,n-1,n-2);
}else{
int i;
for(i=n-1;i>0;--i){
if(arr[i]>arr[i-1])break;
}
if(i==0){//reverse arrangement, n,n-1,...,1
for(;i<n;++i)arr[i] = i;
return ;
}
i=i-1;
for(int j=n-1;j>i;j--){
if(arr[j]>arr[i]){
int tmp = arr[j];
for(int k = j;k>i;--k)arr[k] = arr[k-1];
arr[i] =tmp;
break;
}
}
}
}
void printArr(int *arr,int n)
{
for(int i=0;i<n;++i)printf("%d ",arr[i]);
printf("\n");
}
int main()
{
int n = 4;
int a[n];
for(int i=0;i<n;++i)a[i]=i;
long long int fac=1;
for(int i=2;i<=n;++i)fac*=i;
for(int i=0;i<fac;++i){
printf("rank %d :",i);
printArr(a,n);
nextArrangement(a,n);
}
}

38
math/cantor.c Normal file
View File

@ -0,0 +1,38 @@
#include<stdio.h>
//使用康托展开计算全排列, 下面存储的是0!,1!,2!...(n-1)!
long long int fac[100]={};
void calFac(int n)
{
int i;
fac[0]=1;
for(i=1;i<=n;i++){
fac[i]=i*fac[i-1];
}
}
void getArrangement(int *arr,int n,int sum)
{
/*sum表示全排列由小到大排序后的名次,从0 开始计数, 由名次求出 n位的排列存储到 arr 中*/
int i,j,ct=0,k, ct2;
int flag[n];
for(i=0;i<n;i++)flag[i]=1;
for(i=n-1;i>=0;i--){
for(j=i;j>=0;j--){
if(j*fac[i]<=sum){
ct2=0;
for(k=0;k<n;++k){
//printf("i%d j%d k%d\n",i,j,k);
if(flag[k]==1)ct2++;
if(ct2>j)break;
}
arr[ct++] = k;
flag[k]=0;
sum -=j*fac[i];
break;
}
}
}
}

View File

@ -1,36 +0,0 @@
/* mbinary
#########################################################################
# File : cantor.cc
# Author: mbinary
# Mail: zhuheqin1@gmail.com
# Blog: https://mbinary.coding.me
# Github: https://github.com/mbinary
# Created Time: 2018-05-19 23:06
# Description:
#########################################################################
*/
#include<iostream>
#include<stdio.h>
using namespace std;
int main()
{
float f;
while(cin.peek()!='E'){
cin>>f;
getchar();
bool flag=true;
for(int i=0;i<50&&(f-0.0000001)>0;++i){
int t=3*f;
f=3*f-t;
cout<<f<<endl;
if(t==1){
cout<<"NON-MEMBER"<<endl;
flag = false;
break;
}
}
if(flag)cout<<"MEMBER"<<endl;
}
}

23
search/bloomFilter.py Normal file
View File

@ -0,0 +1,23 @@
from bitarray import bitarray
import mmh3
class bloomFilter(set):
def __init__(self,size,hash_count):
super(bloomFilter,self).__init__()
self.bits = bitarray(size)
self.bits.setall(0)
self.size = size
self.hash_count = hash_count
def __len__(self):
return self.size
def __iter__(self):
return iter(self.bits)
def add(self,item):
for i in range(self.hash_count):
idx = mmh3.hash(item,i) % self.size
self.bits[idx]=1
return self
def __contains__(self,item):
idxs = [mmh3.hash(item,i)%self.size for i in range(self.hash_count)]
return all([self.bits[i]==1 for i in idxs])