mirror of
https://github.com/heqin-zhu/algorithm.git
synced 2024-03-22 13:30:46 +08:00
Update bloomFilter, cantor, redblackTrue,matrix_chain_multiply
This commit is contained in:
parent
0c08851597
commit
d1cf579a2b
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -1,5 +1,6 @@
|
|||
.*
|
||||
*.o
|
||||
*.exe
|
||||
__pycache__/**
|
||||
__pycache__
|
||||
!.gitignore
|
||||
*.out
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Algorithm and Data Structures
|
||||
# Algorithm
|
||||
>Notes and codes for learning algorithm and data structures :smiley:
|
||||
|
||||
Some pictures and ideas are from `<<Introduction to Algotithm>>
|
||||
|
|
122
dataStructure/intervalTree.py
Normal file
122
dataStructure/intervalTree.py
Normal 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)
|
|
@ -9,18 +9,6 @@
|
|||
# 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 random import randint, shuffle
|
||||
|
||||
|
@ -30,14 +18,17 @@ class node:
|
|||
self.val =val
|
||||
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):
|
||||
def setChild(self,nd,isLeft):
|
||||
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
|
||||
|
@ -45,7 +36,8 @@ class node:
|
|||
return self.val is not None
|
||||
def __str__(self):
|
||||
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):
|
||||
return f'node({self.val},isBlack={self.isBlack})'
|
||||
class redBlackTree:
|
||||
|
@ -63,6 +55,159 @@ class redBlackTree:
|
|||
if isBlack is None or isBlack:
|
||||
nd.isBlack = True
|
||||
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):
|
||||
''' return a generator of sorted data'''
|
||||
def inOrder(root):
|
||||
|
@ -77,184 +222,6 @@ class redBlackTree:
|
|||
else:
|
||||
yield from inOrder(root.right)
|
||||
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 getHeight(nd):
|
||||
|
@ -280,7 +247,7 @@ class redBlackTree:
|
|||
lst +=[None,None]
|
||||
return level
|
||||
def addBlank(lines):
|
||||
width = 5
|
||||
width = 1+len(str(self.root))
|
||||
sep = ' '*width
|
||||
n = len(lines)
|
||||
for i,oneline in enumerate(lines):
|
||||
|
@ -295,10 +262,10 @@ class redBlackTree:
|
|||
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)
|
||||
|
||||
length = 10 if li==[] else max(len(i) for i in li)//2
|
||||
begin ='\n'+ 'red-black-tree'.rjust(length+14,'-') + '-'*(length)
|
||||
end = '-'*(length*2+14)+'\n'
|
||||
return '\n'.join([begin,*li,end])
|
||||
def __str__(self):
|
||||
return self.display()
|
||||
|
||||
|
@ -318,34 +285,35 @@ def buildTree(n=10,nums=None,visitor=None):
|
|||
rbtree = redBlackTree()
|
||||
print(f'build a red-black tree using {nums}')
|
||||
for i in nums:
|
||||
rbtree.insert(i)
|
||||
rbtree.insert(node(i))
|
||||
if visitor:
|
||||
visitor(rbtree)
|
||||
visitor(rbtree,i)
|
||||
return rbtree,nums
|
||||
def testInsert():
|
||||
def visitor(t):
|
||||
def testInsert(nums=None):
|
||||
def visitor(t,val):
|
||||
print('inserting', val)
|
||||
print(t)
|
||||
rbtree,nums = buildTree(visitor = visitor)
|
||||
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():
|
||||
rbtree,nums = buildTree()
|
||||
def testSuc(nums=None):
|
||||
rbtree,nums = buildTree(nums=nums)
|
||||
for i in rbtree.sort():
|
||||
print(f'{i}\'s suc is {rbtree.getSuccessor(i)}')
|
||||
|
||||
def testDelete():
|
||||
#nums = [2,3,3,2,6,7,2,1]
|
||||
nums = None
|
||||
def testDelete(nums=None):
|
||||
rbtree,nums = buildTree(nums = nums)
|
||||
print(rbtree)
|
||||
for i in nums:
|
||||
for i in sorted(nums):
|
||||
print(f'deleting {i}')
|
||||
rbtree.delete(i)
|
||||
print(rbtree)
|
||||
|
||||
if __name__=='__main__':
|
||||
#testSuc()
|
||||
#testInsert()
|
||||
lst =[45, 30, 64, 36, 95, 38, 76, 34, 50, 1]
|
||||
lst = [0,3,5,6,26,25,8,19,15,16,17]
|
||||
#testSuc(lst)
|
||||
#testInsert(lst)
|
||||
testDelete()
|
||||
|
|
339
dataStructure/redBlackTree0.py
Normal file
339
dataStructure/redBlackTree0.py
Normal 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()
|
124
divideAndConquer/min_distance_of_n_points.py
Normal file
124
divideAndConquer/min_distance_of_n_points.py
Normal 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)
|
||||
|
|
@ -37,7 +37,7 @@ description:
|
|||
|
||||
<a id="markdown-1-关键字" name="1-关键字"></a>
|
||||
# 1. 关键字
|
||||
由于关键字是用来索引数据的, 所以要求它不能变动(如果变动,实际上就是一个新的关键字插入了), 在python 中表现为 imutable. 常为字符串.
|
||||
由于关键字是用来索引数据的, 所以要求它不能变动(如果变动,实际上就是一个新的关键字插入了), 在python 中表现为 immutable. 常为字符串.
|
||||
|
||||
<a id="markdown-2-映射" name="2-映射"></a>
|
||||
# 2. 映射
|
||||
|
|
|
@ -7,7 +7,6 @@ keywords:
|
|||
mathjax: true
|
||||
description:
|
||||
---
|
||||
|
||||
<!-- TOC -->
|
||||
|
||||
- [1. 定义与性质](#1-定义与性质)
|
||||
|
@ -47,7 +46,6 @@ description:
|
|||
* right:pointer to right child
|
||||
* p: pointer to nil leaf
|
||||
|
||||
|
||||
<a id="markdown-12-红黑性质" name="12-红黑性质"></a>
|
||||
## 1.2. 红黑性质
|
||||
满足下面的 `红黑性质` 的二叉查找树就是红黑树:
|
||||
|
@ -57,7 +55,6 @@ description:
|
|||
* 红结点的孩子是黑
|
||||
* 从每个结点出发,通过子孙到达叶子结点的各条路径上 黑结点数相等
|
||||
|
||||
|
||||
如,叶子结点 是 nil, 即不存储任何东西, 为了编程方便,相对的,存有数据的结点称为内结点
|
||||
![](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 , 颜色设为红色
|
||||
* 最后再进行颜色调整以及旋转(维持红黑性质)
|
||||
|
||||
|
||||
这是算法导论[^1]上的算法
|
||||
```python
|
||||
RB-INSERT(T, z)
|
||||
|
@ -198,7 +194,11 @@ RB-INSERT(T, z)
|
|||
### 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, 不重不漏了吗?
|
||||
|
@ -287,12 +287,10 @@ color[root[T]] ← BLACK
|
|||
|
||||
* 当 z 孩子全是 nil (y==z): 直接让其双亲对应的孩子为 nil
|
||||
* 当 z 只有一个非 nil 孩子 x (y==z):
|
||||
|
||||
1. 如果 z 为根, 则让 x 为根.
|
||||
2. 让 y 的双亲连接到 x
|
||||
* 当 z 有两个非nil孩子(y!=z): 复制其后继 y 的内容到 z (除了指针,颜色) , 将其后继 y 的孩子(最多只有一个 非 nil ,不然就不是后继了)连接到其后继的双亲, 删除 其后继y,
|
||||
|
||||
|
||||
即[^3] 如果要删除有两个孩子的结点 z , 则找到它的后继y(前趋同理), 可以推断 y 一定没有左孩子, 右孩子可能有,可能没有. 也就是最多一个孩子.
|
||||
所以将 y 的值复制到 x 位置, 现在相当于删除 y 处的结点.
|
||||
这样就化为 删除的结点最多一个孩子的情况.
|
||||
|
@ -321,7 +319,6 @@ color[root[T]] ← BLACK
|
|||
* x 指向根,这时可以简单地消除额外的黑色
|
||||
* 颜色修改与旋转
|
||||
|
||||
|
||||
在 while 中, x 总是指向具有双重黑色的那个非根结点, 在第 2 行中要判断 x 是其双亲的左右孩子
|
||||
w 表示 x 的相抵. w 不能为 nil(因为 x 是双重黑色)
|
||||
|
||||
|
@ -330,20 +327,19 @@ w 表示 x 的相抵. w 不能为 nil(因为 x 是双重黑色)
|
|||
|
||||
即
|
||||
* x 的兄弟 w 是红色的
|
||||
|
||||
![](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 的孩子是红色的
|
||||
|
||||
|
||||
>>注意上面都是先考虑的左边, 右边可以对称地处理.
|
||||
|
||||
同插入一样, 为了便于理解, 可以作出状态机.
|
||||
而且这些情形都是归纳化简了的, 你也可以枚举列出基本的全部情形.
|
||||
![](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>
|
||||
# 5. 数据结构的扩张
|
||||
|
@ -374,27 +370,22 @@ def find(root,i):
|
|||
<a id="markdown-6-python-代码" name="6-python-代码"></a>
|
||||
# 6. python 代码
|
||||
|
||||
**[github地址](https://github.com/mbinary/algorithm-and-data-structure.git)**
|
||||
**[github地址](https://github.com/mbinary/algorithm-in-python.git)**
|
||||
|
||||
我的代码有两点不同
|
||||
* 用了 setChild, getChild 来简化代码量
|
||||
* 每个结点没有上面的 p 域, 即指向 nil leaf的,我直接让 left, right 为 `None`, 然后定义了两个函数 `setBlack`, `checkBlack` 来操作 颜色数据 isBlack(当为 True 时代表黑色,否则为红). 如果为 None, 这两个函数也能正确的处理.可以直接见代码
|
||||
|
||||
|
||||
其他的基本上是按照算法导论上的伪代码提到的case 来实现的. 然后display 只是测试的时候,为了方便调试而层序遍历打印出来
|
||||
我用了 setChild, getChild 来简化代码量, 其他的基本上是按照算法导论上的伪代码提到的case 来实现的. 然后display 只是测试的时候,为了方便调试而层序遍历打印出来
|
||||
|
||||
效果如下
|
||||
![](https://upload-images.jianshu.io/upload_images/7130568-721e18cc44dec604.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
|
||||
|
||||
```python
|
||||
'''
|
||||
''' mbinary
|
||||
#########################################################################
|
||||
# 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
|
||||
# Created Time: 2018-07-14 16:15
|
||||
# Description:
|
||||
#########################################################################
|
||||
'''
|
||||
|
@ -407,14 +398,17 @@ class node:
|
|||
self.val =val
|
||||
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):
|
||||
def setChild(self,nd,isLeft):
|
||||
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
|
||||
|
@ -422,7 +416,8 @@ class node:
|
|||
return self.val is not None
|
||||
def __str__(self):
|
||||
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):
|
||||
return f'node({self.val},isBlack={self.isBlack})'
|
||||
class redBlackTree:
|
||||
|
@ -440,6 +435,159 @@ class redBlackTree:
|
|||
if isBlack is None or isBlack:
|
||||
nd.isBlack = True
|
||||
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):
|
||||
''' return a generator of sorted data'''
|
||||
def inOrder(root):
|
||||
|
@ -454,184 +602,6 @@ class redBlackTree:
|
|||
else:
|
||||
yield from inOrder(root.right)
|
||||
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 getHeight(nd):
|
||||
|
@ -657,7 +627,7 @@ class redBlackTree:
|
|||
lst +=[None,None]
|
||||
return level
|
||||
def addBlank(lines):
|
||||
width = 5
|
||||
width = 1+len(str(self.root))
|
||||
sep = ' '*width
|
||||
n = len(lines)
|
||||
for i,oneline in enumerate(lines):
|
||||
|
@ -672,15 +642,18 @@ class redBlackTree:
|
|||
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)
|
||||
|
||||
length = 10 if li==[] else max(len(i) for i in li)//2
|
||||
begin ='\n'+ 'red-black-tree'.rjust(length+14,'-') + '-'*(length)
|
||||
end = '-'*(length*2+14)+'\n'
|
||||
return '\n'.join([begin,*li,end])
|
||||
def __str__(self):
|
||||
return self.display()
|
||||
|
||||
|
||||
```
|
||||
测试代码
|
||||
```python
|
||||
|
||||
def genNum(n =10):
|
||||
nums =[]
|
||||
for i in range(n):
|
||||
|
@ -696,36 +669,37 @@ def buildTree(n=10,nums=None,visitor=None):
|
|||
rbtree = redBlackTree()
|
||||
print(f'build a red-black tree using {nums}')
|
||||
for i in nums:
|
||||
rbtree.insert(i)
|
||||
rbtree.insert(node(i))
|
||||
if visitor:
|
||||
visitor(rbtree)
|
||||
visitor(rbtree,i)
|
||||
return rbtree,nums
|
||||
def testInsert():
|
||||
def visitor(t):
|
||||
def testInsert(nums=None):
|
||||
def visitor(t,val):
|
||||
print('inserting', val)
|
||||
print(t)
|
||||
rbtree,nums = buildTree(visitor = visitor)
|
||||
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():
|
||||
rbtree,nums = buildTree()
|
||||
def testSuc(nums=None):
|
||||
rbtree,nums = buildTree(nums=nums)
|
||||
for i in rbtree.sort():
|
||||
print(f'{i}\'s suc is {rbtree.getSuccessor(i)}')
|
||||
|
||||
def testDelete():
|
||||
#nums = [2,3,3,2,6,7,2,1]
|
||||
nums = None
|
||||
def testDelete(nums=None):
|
||||
rbtree,nums = buildTree(nums = nums)
|
||||
print(rbtree)
|
||||
for i in nums:
|
||||
for i in sorted(nums):
|
||||
print(f'deleting {i}')
|
||||
rbtree.delete(i)
|
||||
print(rbtree)
|
||||
|
||||
if __name__=='__main__':
|
||||
#testSuc()
|
||||
#testInsert()
|
||||
lst =[45, 30, 64, 36, 95, 38, 76, 34, 50, 1]
|
||||
lst = [0,3,5,6,26,25,8,19,15,16,17]
|
||||
#testSuc(lst)
|
||||
#testInsert(lst)
|
||||
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
|
||||
[^3]: https://www.jianshu.com/p/0b68b992f688?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation
|
||||
|
||||
|
|
|
@ -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
|
32
dynamicProgramming/matrixChainMultiply.py
Normal file
32
dynamicProgramming/matrixChainMultiply.py
Normal 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
52
math/arrangement.c
Normal 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
38
math/cantor.c
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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
23
search/bloomFilter.py
Normal 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])
|
Loading…
Reference in New Issue
Block a user