From d1cf579a2bd4f60e1b075c966858b52e5529a95d Mon Sep 17 00:00:00 2001 From: mbinary Date: Wed, 7 Nov 2018 16:52:55 +0800 Subject: [PATCH] Update bloomFilter, cantor, redblackTrue,matrix_chain_multiply --- .gitignore | 3 +- README.md | 2 +- dataStructure/intervalTree.py | 122 ++++++ dataStructure/redBlackTree.py | 388 ++++++++--------- dataStructure/redBlackTree0.py | 339 +++++++++++++++ divideAndConquer/min_distance_of_n_points.py | 124 ++++++ docs/hashTable.md | 2 +- docs/red-black-tree.md | 415 +++++++++---------- dynamicProgramming/matrix-multiply.py | 16 - dynamicProgramming/matrixChainMultiply.py | 32 ++ math/arrangement.c | 52 +++ math/cantor.c | 38 ++ math/cantor.cc | 36 -- search/bloomFilter.py | 23 + 14 files changed, 1107 insertions(+), 485 deletions(-) create mode 100644 dataStructure/intervalTree.py create mode 100644 dataStructure/redBlackTree0.py create mode 100644 divideAndConquer/min_distance_of_n_points.py delete mode 100644 dynamicProgramming/matrix-multiply.py create mode 100644 dynamicProgramming/matrixChainMultiply.py create mode 100644 math/arrangement.c create mode 100644 math/cantor.c delete mode 100644 math/cantor.cc create mode 100644 search/bloomFilter.py diff --git a/.gitignore b/.gitignore index c064458..2f1dfa7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ .* *.o *.exe -__pycache__/** +__pycache__ !.gitignore +*.out diff --git a/README.md b/README.md index f9f21d0..60cdf13 100644 --- a/README.md +++ b/README.md @@ -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 `<> diff --git a/dataStructure/intervalTree.py b/dataStructure/intervalTree.py new file mode 100644 index 0000000..1f3eb85 --- /dev/null +++ b/dataStructure/intervalTree.py @@ -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) diff --git a/dataStructure/redBlackTree.py b/dataStructure/redBlackTree.py index 73ce868..afb3e36 100644 --- a/dataStructure/redBlackTree.py +++ b/dataStructure/redBlackTree.py @@ -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 ndval: - 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() diff --git a/dataStructure/redBlackTree0.py b/dataStructure/redBlackTree0.py new file mode 100644 index 0000000..13c19ba --- /dev/null +++ b/dataStructure/redBlackTree0.py @@ -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 ndval) + 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() diff --git a/divideAndConquer/min_distance_of_n_points.py b/divideAndConquer/min_distance_of_n_points.py new file mode 100644 index 0000000..ea1da6f --- /dev/null +++ b/divideAndConquer/min_distance_of_n_points.py @@ -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.xd2: + 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= 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 # 1. 关键字 -由于关键字是用来索引数据的, 所以要求它不能变动(如果变动,实际上就是一个新的关键字插入了), 在python 中表现为 imutable. 常为字符串. +由于关键字是用来索引数据的, 所以要求它不能变动(如果变动,实际上就是一个新的关键字插入了), 在python 中表现为 immutable. 常为字符串. # 2. 映射 diff --git a/docs/red-black-tree.md b/docs/red-black-tree.md index c5ec804..c92e615 100644 --- a/docs/red-black-tree.md +++ b/docs/red-black-tree.md @@ -7,7 +7,6 @@ keywords: mathjax: true description: --- - - [1. 定义与性质](#1-定义与性质) @@ -47,7 +46,6 @@ description: * right:pointer to right child * p: pointer to nil leaf - ## 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) + # 5. 数据结构的扩张 @@ -374,28 +370,23 @@ def find(root,i): # 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 -# Description: +# Created Time: 2018-07-14 16:15 +# Description: ######################################################################### ''' from functools import total_ordering @@ -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 ndval: - 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 + diff --git a/dynamicProgramming/matrix-multiply.py b/dynamicProgramming/matrix-multiply.py deleted file mode 100644 index 3f54977..0000000 --- a/dynamicProgramming/matrix-multiply.py +++ /dev/null @@ -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 diff --git a/dynamicProgramming/matrixChainMultiply.py b/dynamicProgramming/matrixChainMultiply.py new file mode 100644 index 0000000..ec3daa4 --- /dev/null +++ b/dynamicProgramming/matrixChainMultiply.py @@ -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) diff --git a/math/arrangement.c b/math/arrangement.c new file mode 100644 index 0000000..9e70d42 --- /dev/null +++ b/math/arrangement.c @@ -0,0 +1,52 @@ +#include + +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(;ii;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 + +//使用康托展开计算全排列, 下面存储的是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=0;i--){ + for(j=i;j>=0;j--){ + if(j*fac[i]<=sum){ + ct2=0; + for(k=0;kj)break; + } + arr[ct++] = k; + flag[k]=0; + sum -=j*fac[i]; + break; + } + } + } +} + diff --git a/math/cantor.cc b/math/cantor.cc deleted file mode 100644 index b52f508..0000000 --- a/math/cantor.cc +++ /dev/null @@ -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 -#include -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<