mirror of
https://github.com/heqin-zhu/algorithm.git
synced 2024-03-22 13:30:46 +08:00
Add LRU
This commit is contained in:
parent
b3a7aa9a9f
commit
936d05bb32
187
dataStructure/LRU/allOne.py
Normal file
187
dataStructure/LRU/allOne.py
Normal file
|
@ -0,0 +1,187 @@
|
|||
''' mbinary
|
||||
#########################################################################
|
||||
# File : allOne.py
|
||||
# Author: mbinary
|
||||
# Mail: zhuheqin1@gmail.com
|
||||
# Blog: https://mbinary.xyz
|
||||
# Github: https://github.com/mbinary
|
||||
# Created Time: 2018-05-19 23:07
|
||||
# Description:
|
||||
#########################################################################
|
||||
'''
|
||||
|
||||
|
||||
class node:
|
||||
def __init__(self, val=None, keys=None, pre=None, next=None):
|
||||
self.val = val
|
||||
self.keys = set() if keys is None else keys
|
||||
self.pre = pre
|
||||
self.next = next
|
||||
|
||||
def __lt__(self, nd):
|
||||
return self.val < nd.val
|
||||
|
||||
|
||||
def __contains__(self, k):
|
||||
return k in self.keys
|
||||
|
||||
def __bool__(self):
|
||||
return len(self.keys) != 0
|
||||
|
||||
def __repr__(self):
|
||||
return 'node({},{})'.format(self.val, self.keys)
|
||||
def addKey(self, key):
|
||||
self.keys.add(key)
|
||||
|
||||
|
||||
def remove(self, key):
|
||||
self.keys.remove(key)
|
||||
|
||||
def getOneKey(self):
|
||||
if self:
|
||||
key = self.keys.pop()
|
||||
self.keys.add(key)
|
||||
return key
|
||||
return None
|
||||
|
||||
|
||||
class allOne:
|
||||
def __init__(self):
|
||||
self.head = self.tail = node(0)
|
||||
self.head.next = self.head
|
||||
self.head.pre = self.head
|
||||
self.val_node = {0: self.head}
|
||||
self.key_value = {}
|
||||
|
||||
def __str__(self):
|
||||
li = list(self.val_node.values())
|
||||
li = [str(i) for i in li]
|
||||
return 'min:{}, max:{}\n'.format(self.head.val,self.tail.val) \
|
||||
+ '\n'.join(li)
|
||||
def __contains__(self,k):
|
||||
return k in self.key_value
|
||||
|
||||
def getMaxKey(self):
|
||||
return self.tail.getOneKey()
|
||||
|
||||
def getMinKey(self):
|
||||
return self.head.getOneKey()
|
||||
|
||||
def getMaxVal(self):
|
||||
k = self.getMaxKey()
|
||||
if k is not None:
|
||||
return self.key_value[k]
|
||||
|
||||
def getMinVal(self):
|
||||
k = self.getMinKey()
|
||||
if k is not None:
|
||||
return self.key_value[k]
|
||||
|
||||
def addIncNode(self, val):
|
||||
# when adding a node,inc 1, so it's guranted that node(val-1) exists
|
||||
self.val_node[val] = node(val)
|
||||
self.val_node[val].pre = self.val_node[val - 1]
|
||||
self.val_node[val].next = self.val_node[val - 1].next
|
||||
self.val_node[val - 1].next.pre = self.val_node[
|
||||
val - 1].next = self.val_node[val]
|
||||
if self.tail.val < val:
|
||||
self.tail = self.val_node[val]
|
||||
if self.head.val > val or self.head.val == 0:
|
||||
self.head = self.val_node[val]
|
||||
|
||||
def addDecNode(self, val):
|
||||
# when adding a node,dec 1, so it's guranted that node(val+1) exists
|
||||
self.val_node[val] = node(val)
|
||||
self.val_node[val].next = self.val_node[val + 1]
|
||||
self.val_node[val].pre = self.val_node[val + 1].pre
|
||||
self.val_node[val + 1].pre.next = self.val_node[
|
||||
val + 1].pre = self.val_node[val]
|
||||
if self.head.val > val:
|
||||
self.head = self.val_node[val]
|
||||
|
||||
def delNode(self, val):
|
||||
self.val_node[val].next.pre = self.val_node[val].pre
|
||||
self.val_node[val].pre.next = self.val_node[val].next
|
||||
if self.tail.val == val: self.tail = self.val_node[val].pre
|
||||
if self.head.val == val: self.head = self.val_node[val].next
|
||||
del self.val_node[val]
|
||||
|
||||
def inc(self, key):
|
||||
''' inc key to value val'''
|
||||
val = 1
|
||||
if key in self.key_value:
|
||||
val += self.key_value[key]
|
||||
self.key_value[key] = val
|
||||
if val not in self.val_node:
|
||||
self.addIncNode(val)
|
||||
self.val_node[val].addKey(key)
|
||||
if val != 1: # key in the pre node
|
||||
preVal = val - 1
|
||||
nd = self.val_node[preVal]
|
||||
if key in nd:
|
||||
nd.remove(key)
|
||||
if not nd:
|
||||
self.delNode(preVal)
|
||||
|
||||
def dec(self, key):
|
||||
if key in self.key_value:
|
||||
self.key_value[key] -= 1
|
||||
val = self.key_value[key]
|
||||
if val == 0:
|
||||
del self.key_value[key]
|
||||
elif val>0:
|
||||
if val not in self.val_node:
|
||||
self.addDecNode(val)
|
||||
# notice that the headnode(0) shouldn't add key
|
||||
self.val_node[val].addKey(key)
|
||||
nextVal = val + 1
|
||||
nd = self.val_node[nextVal]
|
||||
if key in nd:
|
||||
nd.remove(key)
|
||||
if not nd:
|
||||
self.delNode(nextVal)
|
||||
|
||||
def delMinKey(self):
|
||||
key = self.getMinKey()
|
||||
if key is not None:
|
||||
val = self.key_value.pop(key)
|
||||
nd = self.val_node[val]
|
||||
nd.remove(key)
|
||||
if not nd:
|
||||
self.delNode(val)
|
||||
return key
|
||||
def append(self,key):
|
||||
if key in self.key_value:
|
||||
raise Exception(f'[Error]: key "{key}" exists')
|
||||
if self.key_value:
|
||||
val = self.key_value[self.getMaxKey()]
|
||||
self.key_value[key] = val
|
||||
self.val_node[val].addKey(key)
|
||||
self.inc(key)
|
||||
def move_to_end(self,key):
|
||||
val = self.key_value.pop(key)
|
||||
nd = self.val_node[val]
|
||||
nd.remove(key)
|
||||
if not nd:
|
||||
self.delNode(val)
|
||||
self.append(key)
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
ops = [
|
||||
"inc", "inc", "inc", "inc", "inc", "dec", "dec", "getMaxKey",
|
||||
"getMinKey",'dec'
|
||||
]
|
||||
obj = allOne()
|
||||
data = [["a"], ["b"], ["b"], ["b"], ["b"], ["b"], ["b"], [], [],['a']]
|
||||
operate = {
|
||||
"inc": obj.inc,
|
||||
"dec": obj.dec,
|
||||
"getMaxKey": obj.getMaxKey,
|
||||
"getMinKey": obj.getMinKey
|
||||
}
|
||||
for op, datum in zip(ops, data):
|
||||
print(f'{op}({datum}): {operate[op](*datum)}')
|
||||
print(obj)
|
||||
print()
|
36
dataStructure/LRU/lru_allone.py
Normal file
36
dataStructure/LRU/lru_allone.py
Normal file
|
@ -0,0 +1,36 @@
|
|||
from allOne import allOne
|
||||
|
||||
'''In this implementation, the lru doesn't use some funcs of allOne,
|
||||
such as dec,addDecNode
|
||||
'''
|
||||
class lru:
|
||||
def __init__(self, capacity):
|
||||
self.capacity = capacity
|
||||
self.allOne = allOne()
|
||||
self.data = {}
|
||||
def get(self,key):
|
||||
if key in self.data:
|
||||
self.allOne.move_to_end(key)
|
||||
return self.data[key]
|
||||
return -1
|
||||
def put(self,key,value):
|
||||
if key not in self.data:
|
||||
if len(self.data)==self.capacity:
|
||||
k = self.allOne.delMinKey()
|
||||
if k in self.data:
|
||||
del self.data[k]
|
||||
self.data[key]=value
|
||||
self.allOne.append(key)
|
||||
else:
|
||||
self.data[key]=value
|
||||
self.allOne.move_to_end(key)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
ops = ["put","put","get","put","get","put","get","get","get"]
|
||||
data = [[1,1],[2,2],[1],[3,3],[2],[4,4],[1],[3],[4]]
|
||||
obj = lru(2)
|
||||
operate = {'get':obj.get,'put':obj.put}
|
||||
for op, args in zip(ops,data):
|
||||
print(f'{op}({args}): {operate[op](*args)}\n{obj.data}\n')
|
||||
|
14
dataStructure/LRU/lru_orderedDict.py
Normal file
14
dataStructure/LRU/lru_orderedDict.py
Normal file
|
@ -0,0 +1,14 @@
|
|||
class LRUCache(object):
|
||||
|
||||
def __init__(self, capacity):
|
||||
self.od, self.cap = collections.OrderedDict(), capacity
|
||||
|
||||
def get(self, key):
|
||||
if key not in self.od: return -1
|
||||
self.od.move_to_end(key)
|
||||
return self.od[key]
|
||||
|
||||
def put(self, key, value):
|
||||
if key in self.od: del self.od[key]
|
||||
elif len(self.od) == self.cap: self.od.popitem(False)
|
||||
self.od[key] = value
|
|
@ -10,7 +10,7 @@
|
|||
#########################################################################
|
||||
'''
|
||||
|
||||
from allOone import AllOne
|
||||
from allOne import allOne
|
||||
from time import time
|
||||
from random import choice,sample,randint
|
||||
|
||||
|
@ -49,12 +49,18 @@ def testCase(n=1000):
|
|||
def test(repeat=100):
|
||||
t1,t2=0,0
|
||||
for i in range(repeat):
|
||||
allOne = AllOne()
|
||||
obj = allOne()
|
||||
operate = {
|
||||
"inc": obj.inc,
|
||||
"dec": obj.dec,
|
||||
"getMaxKey": obj.getMaxKey,
|
||||
"getMinKey": obj.getMinKey
|
||||
}
|
||||
hsmp = hashMap()
|
||||
ops,data = testCase()
|
||||
t1-=time()
|
||||
for op,datum in zip(ops,data):
|
||||
allOne.op[op](*datum)
|
||||
operate[op](*datum)
|
||||
t1+=time()
|
||||
|
||||
t2-=time()
|
||||
|
@ -66,5 +72,5 @@ def test(repeat=100):
|
|||
|
||||
if __name__=='__main__':
|
||||
t1,t2= test()
|
||||
print(f'allOone: {t1}')
|
||||
print(f'allOne: {t1}')
|
||||
print(f'hashmap: {t2}')
|
|
@ -1,213 +0,0 @@
|
|||
''' mbinary
|
||||
#########################################################################
|
||||
# File : allOoneDS.py
|
||||
# Author: mbinary
|
||||
# Mail: zhuheqin1@gmail.com
|
||||
# Blog: https://mbinary.xyz
|
||||
# Github: https://github.com/mbinary
|
||||
# Created Time: 2018-05-19 23:07
|
||||
# Description:
|
||||
#########################################################################
|
||||
'''
|
||||
|
||||
class node:
|
||||
def __init__(self,val=None,data_mp=None,pre=None,next=None):
|
||||
self.val=val
|
||||
self.data_mp = {} if data_mp is None else data_mp
|
||||
self.pre=pre
|
||||
self.next=next
|
||||
def __lt__(self,nd):
|
||||
return self.val<nd.val
|
||||
def getOne(self):
|
||||
if not self.data_mp:
|
||||
return ''
|
||||
else:return list(self.data_mp.items())[0][0]
|
||||
def __getitem__(self,key):
|
||||
return self.data_mp[key]
|
||||
def __iter__(self):
|
||||
return iter(self.data_mp)
|
||||
def __delitem__(self,key):
|
||||
del self.data_mp[key]
|
||||
def __setitem__(self,key,val):
|
||||
self.data_mp[key]= val
|
||||
def isEmpty(self):
|
||||
return self.data_mp=={}
|
||||
def __repr__(self):
|
||||
return 'node({},{})'.format(self.val,self.data_mp)
|
||||
class doubleLinkedList:
|
||||
def __init__(self):
|
||||
self.head= self.tail = node(0)
|
||||
self.head.next = self.head
|
||||
self.head.pre = self.head
|
||||
self.chain_mp={0:self.head}
|
||||
def __str__(self):
|
||||
li = list(self.chain_mp.values())
|
||||
li = [str(i) for i in li]
|
||||
return 'min:{}, max:{}\n'.format(self.head.val,self.tail.val) \
|
||||
+ '\n'.join(li)
|
||||
def getMax(self):
|
||||
return self.tail.getOne()
|
||||
def getMin(self):
|
||||
return self.head.getOne()
|
||||
def addIncNode(self,val):
|
||||
# when adding a node,inc 1, so it's guranted that node(val-1) exists
|
||||
self.chain_mp[val].pre= self.chain_mp[val-1]
|
||||
self.chain_mp[val].next= self.chain_mp[val-1].next
|
||||
self.chain_mp[val-1].next.pre = self.chain_mp[val-1].next = self.chain_mp[val]
|
||||
def addDecNode(self,val):
|
||||
# when adding a node,dec 1, so it's guranted that node(val+1) exists
|
||||
self.chain_mp[val].next= self.chain_mp[val+1]
|
||||
self.chain_mp[val].pre= self.chain_mp[val+1].pre
|
||||
self.chain_mp[val+1].pre.next = self.chain_mp[val+1].pre = self.chain_mp[val]
|
||||
def addNode(self,val,dec=False):
|
||||
self.chain_mp[val] = node(val)
|
||||
if dec:self.addDecNode(val)
|
||||
else:self.addIncNode(val)
|
||||
if self.tail.val<val:self.tail = self.chain_mp[val]
|
||||
if self.head.val>val or self.head.val==0:self.head= self.chain_mp[val]
|
||||
def delNode(self,val):
|
||||
self.chain_mp[val].next.pre = self.chain_mp[val].pre
|
||||
self.chain_mp[val].pre.next = self.chain_mp[val].next
|
||||
if self.tail.val==val:self.tail = self.chain_mp[val].pre
|
||||
if self.head.val==val:self.head = self.chain_mp[val].next
|
||||
del self.chain_mp[val]
|
||||
def incTo(self,key,val):
|
||||
if val not in self.chain_mp:
|
||||
self.addNode(val)
|
||||
self.chain_mp[val][key] = val
|
||||
if val!=1 : # key in the pre node
|
||||
del self.chain_mp[val-1][key]
|
||||
#print(self.chain_mp[val-1])
|
||||
if self.chain_mp[val-1].isEmpty():
|
||||
#print('*'*20)
|
||||
self.delNode(val-1)
|
||||
def decTo(self,key,val):
|
||||
if val not in self.chain_mp:
|
||||
self.addNode(val,dec=True)
|
||||
# notice that the headnode(0) shouldn't add key
|
||||
if val!=0: self.chain_mp[val][key] = val
|
||||
del self.chain_mp[val+1][key]
|
||||
if self.chain_mp[val+1].isEmpty():
|
||||
self.delNode(val+1)
|
||||
|
||||
class AllOne:
|
||||
def __init__(self):
|
||||
"""
|
||||
Initialize your data structure here.
|
||||
"""
|
||||
self.op = {"inc":self.inc,"dec":self.dec,"getMaxKey":self.getMaxKey,"getMinKey":self.getMinKey}
|
||||
self.mp = {}
|
||||
self.dll = doubleLinkedList()
|
||||
def __str__(self):
|
||||
return str(self.dll)
|
||||
def __getitem__(self,key):
|
||||
return self.mp[key]
|
||||
def __delitem__(self,key):
|
||||
del self.mp[key]
|
||||
def __setitem__(self,key,val):
|
||||
self.mp[key]= val
|
||||
def __iter__(self):
|
||||
return iter(self.mp)
|
||||
def inc(self, key,n=1):
|
||||
"""
|
||||
Inserts a new key <Key> with value 1. Or increments an existing key by 1.
|
||||
:type key: str
|
||||
:rtype: void
|
||||
"""
|
||||
if key in self:
|
||||
self[key]+=n
|
||||
else:self[key]=n
|
||||
for i in range(n): self.dll.incTo(key, self[key])
|
||||
def dec(self, key,n=1):
|
||||
"""
|
||||
Decrements an existing key by 1. If Key's value is 1, remove it from the data structure.
|
||||
:type key: str
|
||||
:rtype: void
|
||||
"""
|
||||
if key in self.mp:
|
||||
mn = min( self[key],n)
|
||||
for i in range(mn): self.dll.decTo(key, self[key]-i-1)
|
||||
if self[key] == n:
|
||||
del self[key]
|
||||
else:
|
||||
self[key] = self[key]-n
|
||||
def getMaxKey(self):
|
||||
"""
|
||||
Returns one of the keys with maximal value.
|
||||
:rtype: str
|
||||
"""
|
||||
return self.dll.getMax()
|
||||
|
||||
def getMinKey(self):
|
||||
"""
|
||||
Returns one of the keys with Minimal value.
|
||||
:rtype: str
|
||||
"""
|
||||
return self.dll.getMin()
|
||||
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
ops=["inc","inc","inc","inc","inc","dec","dec","getMaxKey","getMinKey"]
|
||||
data=[["a"],["b"],["b"],["b"],["b"],["b"],["b"],[],[]]
|
||||
obj = AllOne()
|
||||
for op,datum in zip(ops,data):
|
||||
print(obj.op[op](*datum))
|
||||
print(op,datum)
|
||||
print(obj)
|
||||
|
||||
'''
|
||||
None
|
||||
inc ['a']
|
||||
min:1, max:1
|
||||
node(0,{})
|
||||
node(1,{'a': 1})
|
||||
None
|
||||
inc ['b']
|
||||
min:1, max:1
|
||||
node(0,{})
|
||||
node(1,{'a': 1, 'b': 1})
|
||||
None
|
||||
inc ['b']
|
||||
min:1, max:2
|
||||
node(0,{})
|
||||
node(1,{'a': 1})
|
||||
node(2,{'b': 2})
|
||||
None
|
||||
inc ['b']
|
||||
min:1, max:3
|
||||
node(0,{})
|
||||
node(1,{'a': 1})
|
||||
node(3,{'b': 3})
|
||||
None
|
||||
inc ['b']
|
||||
min:1, max:4
|
||||
node(0,{})
|
||||
node(1,{'a': 1})
|
||||
node(4,{'b': 4})
|
||||
None
|
||||
dec ['b']
|
||||
min:1, max:3
|
||||
node(0,{})
|
||||
node(1,{'a': 1})
|
||||
node(3,{'b': 3})
|
||||
None
|
||||
dec ['b']
|
||||
min:1, max:2
|
||||
node(0,{})
|
||||
node(1,{'a': 1})
|
||||
node(2,{'b': 2})
|
||||
b
|
||||
getMaxKey []
|
||||
min:1, max:2
|
||||
node(0,{})
|
||||
node(1,{'a': 1})
|
||||
node(2,{'b': 2})
|
||||
a
|
||||
getMinKey []
|
||||
min:1, max:2
|
||||
node(0,{})
|
||||
node(1,{'a': 1})
|
||||
node(2,{'b': 2})
|
||||
'''
|
|
@ -10,144 +10,175 @@
|
|||
#########################################################################
|
||||
'''
|
||||
|
||||
from collections import Iterable,deque
|
||||
from collections import Iterable, deque
|
||||
|
||||
|
||||
class vertex:
|
||||
def __init__(self,mark,firstEdge=None,val=None):
|
||||
def __init__(self, mark, firstEdge=None, val=None):
|
||||
self.mark = mark
|
||||
self.val = val
|
||||
self.firstEdge = firstEdge
|
||||
self.isVisited = False
|
||||
|
||||
def __str__(self):
|
||||
return 'V'+str(self.mark)
|
||||
return 'V' + str(self.mark)
|
||||
|
||||
def __repr__(self):
|
||||
return str(self)
|
||||
|
||||
|
||||
class edge:
|
||||
def __init__(self,adjVertexs, weight = 1,nextEdge=None):
|
||||
def __init__(self, adjVertexs, weight=1, nextEdge=None):
|
||||
'''adjVertexs:tuple(v.mark,u.mark)'''
|
||||
self.weight = weight
|
||||
self.adjVertexs = adjVertexs
|
||||
self.nextEdge = nextEdge
|
||||
self.isVisted = False
|
||||
def __add__(self,x):
|
||||
return self.weight +x
|
||||
def __radd__(self,x):
|
||||
return self+x
|
||||
def __getitem__(self,k):
|
||||
if k!=0 or k!=1:raise IndexError
|
||||
|
||||
def __add__(self, x):
|
||||
return self.weight + x
|
||||
|
||||
def __radd__(self, x):
|
||||
return self + x
|
||||
|
||||
def __getitem__(self, k):
|
||||
if k != 0 or k != 1: raise IndexError
|
||||
return self.adjVertexs[k]
|
||||
|
||||
def __str__(self):
|
||||
return '--'+str(self.weight)+'--'
|
||||
return '--' + str(self.weight) + '--'
|
||||
|
||||
def __repr__(self):
|
||||
return str(self)
|
||||
|
||||
@property
|
||||
def v(self):
|
||||
return self.adjVertexs[0]
|
||||
|
||||
@property
|
||||
def u(self):
|
||||
return self.adjVertexs[1]
|
||||
|
||||
|
||||
class graph:
|
||||
def __init__(self):
|
||||
def __init__(self):
|
||||
self.vertexs = {}
|
||||
self.edges = {}
|
||||
def __getitem__(self,i):
|
||||
|
||||
def __getitem__(self, i):
|
||||
return self.vertexs[i]
|
||||
def __setitem__(selfi,x):
|
||||
self.vertexs[i]= x
|
||||
|
||||
def __setitem__(selfi, x):
|
||||
self.vertexs[i] = x
|
||||
|
||||
def __iter__(self):
|
||||
return iter(self.vertexs)
|
||||
def __bool__(self):
|
||||
return len(self.vertexs)!=0
|
||||
def addVertex(self,vertexs):
|
||||
'''vertexs is a iterable or just a mark that marks the vertex,whichc can be every imutable type'''
|
||||
if not isinstance(vertexs,Iterable):vertexs=[vertexs]
|
||||
for i in vertexs:
|
||||
if not isinstance(i,vertex) and i not in self.vertexs:self.vertexs[i]= vertex(i)
|
||||
if isinstance(i,vertex) and i not in self.vertexs:self.vertexs[i.mark]= i
|
||||
|
||||
def __getVertex(self,v):
|
||||
if not isinstance(v,vertex):
|
||||
def __bool__(self):
|
||||
return len(self.vertexs) != 0
|
||||
|
||||
def addVertex(self, vertexs):
|
||||
'''vertexs is a iterable or just a mark that marks the vertex,whichc can be every imutable type'''
|
||||
if not isinstance(vertexs, Iterable): vertexs = [vertexs]
|
||||
for i in vertexs:
|
||||
if not isinstance(i, vertex) and i not in self.vertexs:
|
||||
self.vertexs[i] = vertex(i)
|
||||
if isinstance(i, vertex) and i not in self.vertexs:
|
||||
self.vertexs[i.mark] = i
|
||||
|
||||
def __getVertex(self, v):
|
||||
if not isinstance(v, vertex):
|
||||
if v not in self.vertexs:
|
||||
self.vertexs[v]=vertex(v)
|
||||
self.vertexs[v] = vertex(v)
|
||||
return self.vertexs[v]
|
||||
return v
|
||||
def addEdge(self,v,u,weight = 1):
|
||||
|
||||
def addEdge(self, v, u, weight=1):
|
||||
v = self.__getVertex(v)
|
||||
u = self.__getVertex(u)
|
||||
arc = self.findEdge(v,u)
|
||||
if arc!=None:return #examine that if v,u have been already connected
|
||||
vertexs = (v,u)
|
||||
newEdge = edge (vertexs,weight)
|
||||
arc = self.findEdge(v, u)
|
||||
if arc != None:
|
||||
return #examine that if v,u have been already connected
|
||||
vertexs = (v, u)
|
||||
newEdge = edge(vertexs, weight)
|
||||
self.edges[vertexs] = newEdge
|
||||
if v.firstEdge==None:
|
||||
v.firstEdge=newEdge
|
||||
if v.firstEdge == None:
|
||||
v.firstEdge = newEdge
|
||||
else:
|
||||
arc=v.firstEdge.nextEdge
|
||||
v.firstEdge=newEdge
|
||||
def findEdge(self,v,u):
|
||||
arc = v.firstEdge.nextEdge
|
||||
v.firstEdge = newEdge
|
||||
|
||||
def findEdge(self, v, u):
|
||||
v = self.__getVertex(v)
|
||||
u = self.__getVertex(u)
|
||||
arc = v.firstEdge
|
||||
while arc!=None and u not in arc:
|
||||
while arc != None and u not in arc:
|
||||
arc = arc.nextEdge
|
||||
if arc!=None:return arc
|
||||
if arc != None: return arc
|
||||
arc = u.firstEdge
|
||||
while arc!=None and v not in arc:
|
||||
while arc != None and v not in arc:
|
||||
arc = arc.nextEdge
|
||||
return arc
|
||||
def delEdge(self,v,u):
|
||||
if not isinstance(v,vertex):v= self.vertexs[v]
|
||||
if not isinstance(u,vertex):u= self.vertexs[u]
|
||||
if u in v.firstEdge:
|
||||
v.firstEdge =v.firstEdge.nextEdge
|
||||
|
||||
def delEdge(self, v, u):
|
||||
if not isinstance(v, vertex): v = self.vertexs[v]
|
||||
if not isinstance(u, vertex): u = self.vertexs[u]
|
||||
if u in v.firstEdge:
|
||||
v.firstEdge = v.firstEdge.nextEdge
|
||||
else:
|
||||
arc = v.firstEdge
|
||||
while arc.nextEdge!=e:
|
||||
while arc.nextEdge != e:
|
||||
arc = arc.nextEdge
|
||||
if arc!=None: arc.nextEdge = arc.nextEdge.nextEdge
|
||||
if arc != None: arc.nextEdge = arc.nextEdge.nextEdge
|
||||
else:
|
||||
if v in u.firstEdge:
|
||||
u.firstEdge =u.firstEdge.nextEdge
|
||||
if v in u.firstEdge:
|
||||
u.firstEdge = u.firstEdge.nextEdge
|
||||
else:
|
||||
arc = u.firstEdge
|
||||
while arc.nextEdge!=e:
|
||||
while arc.nextEdge != e:
|
||||
arc = arc.nextEdge
|
||||
arc.nextEdge = arc.nextEdge.nextEdge
|
||||
del self.edges[(v,u)]
|
||||
del self.edges[(v, u)]
|
||||
|
||||
def revisit(self):
|
||||
for i in self.vertexs.values():
|
||||
i.isVisited = False
|
||||
for i in self.edges.values():
|
||||
i.isVisited = False
|
||||
|
||||
def __str__(self):
|
||||
arcs= list(self.edges.keys())
|
||||
arcs=[str(i[0])+str(self.edges[i])+str(i[1]) for i in arcs]
|
||||
s= '\n'.join(arcs)
|
||||
arcs = list(self.edges.keys())
|
||||
arcs = [str(i[0]) + str(self.edges[i]) + str(i[1]) for i in arcs]
|
||||
s = '\n'.join(arcs)
|
||||
return s
|
||||
|
||||
def __repr__(self):
|
||||
return str(self)
|
||||
def minPath(self,v,u):
|
||||
if v not in self or u not in self:return -1
|
||||
v=self.__getVertex(v)
|
||||
u=self.__getVertex(u)
|
||||
q=deque([v])
|
||||
last={i:None for i in self.vertexs.values()}
|
||||
|
||||
def minPath(self, v, u):
|
||||
if v not in self or u not in self: return -1
|
||||
v = self.__getVertex(v)
|
||||
u = self.__getVertex(u)
|
||||
q = deque([v])
|
||||
last = {i: None for i in self.vertexs.values()}
|
||||
last[v] = 0
|
||||
ds={i:1000000 for i in self.vertexs.values()}
|
||||
ds[v]=0
|
||||
while len(q)!=0:
|
||||
ds = {i: 1000000 for i in self.vertexs.values()}
|
||||
ds[v] = 0
|
||||
while len(q) != 0:
|
||||
nd = q.popleft()
|
||||
nd.isVisited=True
|
||||
nd.isVisited = True
|
||||
arc = nd.firstEdge
|
||||
while arc!=None:
|
||||
tgt=None
|
||||
if arc.v==nd:
|
||||
while arc != None:
|
||||
tgt = None
|
||||
if arc.v == nd:
|
||||
tgt = arc.u
|
||||
else:tgt = arc.v
|
||||
tmp=ds[nd]+arc
|
||||
if ds[tgt] >tmp:
|
||||
ds[tgt]=tmp
|
||||
else:
|
||||
tgt = arc.v
|
||||
tmp = ds[nd] + arc
|
||||
if ds[tgt] > tmp:
|
||||
ds[tgt] = tmp
|
||||
last[tgt] = nd
|
||||
if not tgt.isVisited:q.append(tgt)
|
||||
if not tgt.isVisited: q.append(tgt)
|
||||
'''
|
||||
cur = u
|
||||
while cur !=v:
|
||||
|
@ -156,36 +187,39 @@ class graph:
|
|||
print(str(v))
|
||||
'''
|
||||
return ds[u]
|
||||
|
||||
def hasCircle(self):
|
||||
pass
|
||||
|
||||
def display(self):
|
||||
print('vertexs')
|
||||
for i in self.vertexs:
|
||||
print(i)
|
||||
print('edges')
|
||||
for i in self.edges:
|
||||
arc=self.edges[i]
|
||||
print(str(arc.v)+str(arc)+str(arc.u))
|
||||
|
||||
if __name__=='__main__':
|
||||
n=int(input())
|
||||
while n>0:
|
||||
cities=int(input())
|
||||
n-=1
|
||||
g=graph()
|
||||
li={}
|
||||
arc = self.edges[i]
|
||||
print(str(arc.v) + str(arc) + str(arc.u))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
n = int(input())
|
||||
while n > 0:
|
||||
cities = int(input())
|
||||
n -= 1
|
||||
g = graph()
|
||||
li = {}
|
||||
for i in range(cities):
|
||||
li[input()]=i+1
|
||||
arc=int(input())
|
||||
li[input()] = i + 1
|
||||
arc = int(input())
|
||||
for j in range(arc):
|
||||
s=input().split(' ')
|
||||
g.addEdge(i+1,int(s[0]),int(s[1]))
|
||||
ct =int(input())
|
||||
for i in range(ct):
|
||||
s = input().split(' ')
|
||||
g.addEdge(i + 1, int(s[0]), int(s[1]))
|
||||
ct = int(input())
|
||||
for i in range(ct):
|
||||
line = input()
|
||||
line= line .split(' ')
|
||||
v,u = li[line[0]],li[line[1]]
|
||||
print(g.minPath(v,u))
|
||||
line = line.split(' ')
|
||||
v, u = li[line[0]], li[line[1]]
|
||||
print(g.minPath(v, u))
|
||||
g.revisit()
|
||||
#http://www.spoj.com/submit/SHPATH/id=20525991
|
||||
'''
|
||||
|
|
|
@ -1,198 +0,0 @@
|
|||
''' mbinary
|
||||
#########################################################################
|
||||
# File : undirected.py
|
||||
# Author: mbinary
|
||||
# Mail: zhuheqin1@gmail.com
|
||||
# Blog: https://mbinary.xyz
|
||||
# Github: https://github.com/mbinary
|
||||
# Created Time: 2018-04-26 10:33
|
||||
# Description:
|
||||
#########################################################################
|
||||
'''
|
||||
|
||||
from collections import Iterable,deque
|
||||
class vertex:
|
||||
def __init__(self,mark,val=None):
|
||||
self.mark = mark
|
||||
self.val = val
|
||||
self.edges = {}
|
||||
self.isVisited = False
|
||||
def __getitem__(self,adjVertexMark):
|
||||
return self.edges[adjVertexMark]
|
||||
def __delitem__(self,k):
|
||||
del self.edges[k]
|
||||
def __iter__(self):
|
||||
return iter(self.edges.values())
|
||||
def __str__(self):
|
||||
return 'V'+str(self.mark)
|
||||
def __repr__(self):
|
||||
return str(self)
|
||||
class edge:
|
||||
def __init__(self,adjVertexs, weight = 1):
|
||||
'''adjVertexs:tuple(v.mark,u.mark)'''
|
||||
self.weight = weight
|
||||
self.adjVertexs = adjVertexs
|
||||
self.isVisted = False
|
||||
def __add__(self,x):
|
||||
return self.weight +x
|
||||
def __radd__(self,x):
|
||||
return self+x
|
||||
def __getitem__(self,k):
|
||||
if k!=0 or k!=1:raise IndexError
|
||||
return self.adjVertexs[k]
|
||||
def __str__(self):
|
||||
return '--'+str(self.weight)+'--'
|
||||
def __repr__(self):
|
||||
return str(self)
|
||||
@property
|
||||
def v(self):
|
||||
return self.adjVertexs[0]
|
||||
@property
|
||||
def u(self):
|
||||
return self.adjVertexs[1]
|
||||
class graph:
|
||||
def __init__(self):
|
||||
self.vertexs = {}
|
||||
self.edges = {}
|
||||
def __getitem__(self,i):
|
||||
return self.vertexs[i]
|
||||
def __setitem__(selfi,x):
|
||||
self.vertexs[i]= x
|
||||
def __iter__(self):
|
||||
return iter(self.vertexs)
|
||||
def __bool__(self):
|
||||
return len(self.vertexs)!=0
|
||||
def addVertex(self,vertexs):
|
||||
'''vertexs is a iterable or just a mark that marks the vertex,whichc can be every imutable type'''
|
||||
if not isinstance(vertexs,Iterable):vertexs=[vertexs]
|
||||
for i in vertexs:
|
||||
if not isinstance(i,vertex) and i not in self.vertexs:self.vertexs[i]= vertex(i)
|
||||
if isinstance(i,vertex) and i not in self.vertexs:self.vertexs[i.mark]= i
|
||||
|
||||
def __getVertex(self,v):
|
||||
if not isinstance(v,vertex):
|
||||
if v not in self.vertexs:
|
||||
self.vertexs[v]=vertex(v)
|
||||
return self.vertexs[v]
|
||||
return v
|
||||
def addEdge(self,v,u,weight = 1):
|
||||
v = self.__getVertex(v)
|
||||
u = self.__getVertex(u)
|
||||
for arc in v:
|
||||
if u in arc.adjVertexs:return #examine that if v,u have been already connected
|
||||
vertexs = (v,u)
|
||||
newEdge = edge (vertexs,weight)
|
||||
self.edges[vertexs] = newEdge
|
||||
v.edges[u] = newEdge
|
||||
u.edges[v] = newEdge
|
||||
def delEdge(self,v,u):
|
||||
if not isinstance(v,vertex):v= self.vertexs[v]
|
||||
if not isinstance(u,vertex):u= self.vertexs[u]
|
||||
try:
|
||||
del v[u]
|
||||
del u[v]
|
||||
except:print("error!"+str(v)+','+str(u)+' arent adjacent now')
|
||||
del self.edges[(v,u)]
|
||||
def revisit(self):
|
||||
for i in self.vertexs.values():
|
||||
i.isVisited = False
|
||||
for i in self.edges.values():
|
||||
i.isVisited = False
|
||||
def __str__(self):
|
||||
arcs= list(self.edges.keys())
|
||||
arcs=[str(i[0])+str(self.edges[i])+str(i[1]) for i in arcs]
|
||||
s= '\n'.join(arcs)
|
||||
return s
|
||||
def __repr__(self):
|
||||
return str(self)
|
||||
def minPath(self,v,u):
|
||||
v=self.__getVertex(v)
|
||||
u=self.__getVertex(u)
|
||||
q=deque([v])
|
||||
last={i:None for i in self.vertexs.values()}
|
||||
last[v] = 0
|
||||
ds={i:1000000 for i in self.vertexs.values()}
|
||||
ds[v]=0
|
||||
while len(q)!=0:
|
||||
nd = q.popleft()
|
||||
nd.isVisited=True
|
||||
for edge in nd:
|
||||
tgt=None
|
||||
if edge.v==nd:
|
||||
tgt = edge.u
|
||||
else:tgt = edge.v
|
||||
tmp=ds[nd]+edge
|
||||
if ds[tgt] >tmp:
|
||||
ds[tgt]=tmp
|
||||
last[tgt] = nd
|
||||
if not tgt.isVisited:q.append(tgt)
|
||||
'''
|
||||
cur = u
|
||||
while cur !=v:
|
||||
print(str(cur)+'<---',end='')
|
||||
cur =last[cur]
|
||||
print(str(v))
|
||||
'''
|
||||
return ds[u]
|
||||
def hasCircle(self):
|
||||
pass
|
||||
def display(self):
|
||||
print('vertexs')
|
||||
for i in self.vertexs:
|
||||
print(i)
|
||||
print('edges')
|
||||
for i in self.edges:
|
||||
arc=self.edges[i]
|
||||
print(str(arc.v)+str(arc)+str(arc.u))
|
||||
|
||||
if __name__=='__main__':
|
||||
n=int(input())
|
||||
while n>0:
|
||||
cities=int(input())
|
||||
n-=1
|
||||
g=graph()
|
||||
li={}
|
||||
for i in range(cities):
|
||||
li[input()]=i+1
|
||||
arc=int(input())
|
||||
for j in range(arc):
|
||||
s=input().split(' ')
|
||||
g.addEdge(i+1,int(s[0]),int(s[1]))
|
||||
ct =int(input())
|
||||
for i in range(ct):
|
||||
line = input()
|
||||
line= line .split(' ')
|
||||
v,u = li[line[0]],li[line[1]]
|
||||
print(g.minPath(v,u))
|
||||
g.revisit()
|
||||
#http://www.spoj.com/submit/SHPATH/id=20525991
|
||||
'''
|
||||
1
|
||||
4
|
||||
gdansk
|
||||
2
|
||||
2 1
|
||||
3 3
|
||||
bydgoszcz
|
||||
3
|
||||
1 1
|
||||
3 1
|
||||
4 4
|
||||
torun
|
||||
3
|
||||
1 3
|
||||
2 1
|
||||
4 1
|
||||
warszawa
|
||||
2
|
||||
2 4
|
||||
3 1
|
||||
2
|
||||
gdansk warszawa
|
||||
bydgoszcz warszawa
|
||||
V4<---V3<---V2<---V1
|
||||
3
|
||||
V4<---V3<---V2
|
||||
2
|
||||
>>>
|
||||
'''
|
|
@ -1,57 +0,0 @@
|
|||
#coding: utf-8
|
||||
''' mbinary
|
||||
#######################################################################
|
||||
# File : wildcard_matching.py
|
||||
# Author: mbinary
|
||||
# Mail: zhuheqin1@gmail.com
|
||||
# Blog: https://mbinary.xyz
|
||||
# Github: https://github.com/mbinary
|
||||
# Created Time: 2018-12-13 22:46
|
||||
# Description:
|
||||
wild card '*' matches 0 or any chars, and '?' matches any single char.
|
||||
#######################################################################
|
||||
'''
|
||||
|
||||
|
||||
'''
|
||||
idea
|
||||
|
||||
dynamic programming
|
||||
|
||||
dp[m+1][n+1]: bool
|
||||
|
||||
i:n, j:m
|
||||
dp[j][i] indicates if s[:i+1] matches p[:j+1]
|
||||
|
||||
initial: dp[0][0] = True, dp[0][i],dp[j][0] = False
|
||||
only if p startswith '*', dp[1][0] = True.
|
||||
|
||||
if p[j] = '*': dp[j][i] = dp[j-1][i] or dp[j][i-1]
|
||||
elif p[j] = '?': dp[j][i] = dp[j-1][i-1]
|
||||
else : dp[j][i] = dp[j-1][i-1] and s[i] == p[j]
|
||||
'''
|
||||
|
||||
# leetcode: q44 https://leetcode.com/problems/wildcard-matching/description/
|
||||
|
||||
def isMatch(self, s, p):
|
||||
"""
|
||||
:type s: str
|
||||
:type p: str pattern str including wildcard
|
||||
:rtype: bool
|
||||
"""
|
||||
n,m = len(s),len(p)
|
||||
last = [False]*(n+1)
|
||||
last[0] = True
|
||||
for j in range(m):
|
||||
if p[j]=='*':
|
||||
for i in range(n):
|
||||
last[i+1] = last[i+1] or last[i]
|
||||
elif p[j]=='?':
|
||||
last.pop()
|
||||
last.insert(0,False)
|
||||
else:
|
||||
li = [False]
|
||||
for i in range(n):
|
||||
li.append( last[i] and p[j]==s[i])
|
||||
last = li
|
||||
return last[-1]
|
|
@ -10,98 +10,122 @@
|
|||
#########################################################################
|
||||
'''
|
||||
|
||||
|
||||
def quickSort(lst):
|
||||
'''A optimized version of Hoare partition'''
|
||||
def partition(a,b):
|
||||
|
||||
def partition(a, b):
|
||||
pivot = lst[a]
|
||||
while a!=b:
|
||||
while a<b and lst[b]>pivot: b-=1
|
||||
if a<b:
|
||||
while a != b:
|
||||
while a < b and lst[b] > pivot:
|
||||
b -= 1
|
||||
if a < b:
|
||||
lst[a] = lst[b]
|
||||
a+=1
|
||||
while a<b and lst[a]<pivot: a+=1
|
||||
if a<b:
|
||||
a += 1
|
||||
while a < b and lst[a] < pivot:
|
||||
a += 1
|
||||
if a < b:
|
||||
lst[b] = lst[a]
|
||||
b-=1
|
||||
b -= 1
|
||||
lst[a] = pivot
|
||||
return a
|
||||
def _sort(a,b):
|
||||
if a>=b:return
|
||||
mid = (a+b)//2
|
||||
|
||||
def _sort(a, b):
|
||||
if a >= b: return
|
||||
mid = (a + b) // 2
|
||||
# 三数取中值置于第一个作为 pivot
|
||||
if (lst[a]<lst[mid]) ^ (lst[b]<lst[mid]): lst[a],lst[mid] = lst[mid],lst[a] # lst[mid] 为中值
|
||||
if (lst[a]<lst[b]) ^ (lst[b]>lst[mid]): lst[a],lst[b] = lst[b],lst[a] # lst[b] 为中值
|
||||
i = partition(a,b)
|
||||
_sort(a,i-1)
|
||||
_sort(i+1,b)
|
||||
_sort(0,len(lst)-1)
|
||||
if (lst[a] < lst[mid]) ^ (lst[b] < lst[mid]):
|
||||
lst[a], lst[mid] = lst[mid], lst[a] # lst[mid] 为中值
|
||||
if (lst[a] < lst[b]) ^ (lst[b] > lst[mid]):
|
||||
lst[a], lst[b] = lst[b], lst[a] # lst[b] 为中值
|
||||
i = partition(a, b)
|
||||
_sort(a, i - 1)
|
||||
_sort(i + 1, b)
|
||||
|
||||
_sort(0, len(lst) - 1)
|
||||
return lst
|
||||
|
||||
|
||||
def quickSort2(lst):
|
||||
'''A version of partition from <Introduction of Algorithm>, a little bit slow'''
|
||||
def partition(a,b):
|
||||
pivot = lst[b]
|
||||
j = a-1
|
||||
for i in range(a,b):
|
||||
if lst[i]<=pivot:
|
||||
j+=1
|
||||
if i!=j: lst[i], lst[j] = lst[j], lst[i]
|
||||
lst[j+1],lst[b] = lst[b],lst[j+1]
|
||||
return j+1
|
||||
def _sort(a,b):
|
||||
if a>=b:return
|
||||
mid = (a+b)//2
|
||||
# 三数取中值置于第一个作为 pivot
|
||||
if (lst[a]<lst[mid]) ^ (lst[b]<lst[mid]): lst[b],lst[mid] = lst[mid],lst[b] # lst[mid] 为中值
|
||||
if (lst[a]>lst[b]) ^ (lst[a]>lst[mid]): lst[a],lst[b] = lst[b],lst[a] # lst[b] 为中值
|
||||
i = partition(a,b)
|
||||
_sort(a,i-1)
|
||||
_sort(i+1,b)
|
||||
|
||||
_sort(0,len(lst)-1)
|
||||
def partition(a, b):
|
||||
pivot = lst[b]
|
||||
j = a - 1
|
||||
for i in range(a, b):
|
||||
if lst[i] <= pivot:
|
||||
j += 1
|
||||
if i != j: lst[i], lst[j] = lst[j], lst[i]
|
||||
lst[j + 1], lst[b] = lst[b], lst[j + 1]
|
||||
return j + 1
|
||||
|
||||
def _sort(a, b):
|
||||
if a >= b: return
|
||||
mid = (a + b) // 2
|
||||
# 三数取中值置于第一个作为 pivot
|
||||
if (lst[a] < lst[mid]) ^ (lst[b] < lst[mid]):
|
||||
lst[b], lst[mid] = lst[mid], lst[b] # lst[mid] 为中值
|
||||
if (lst[a] > lst[b]) ^ (lst[a] > lst[mid]):
|
||||
lst[a], lst[b] = lst[b], lst[a] # lst[b] 为中值
|
||||
i = partition(a, b)
|
||||
_sort(a, i - 1)
|
||||
_sort(i + 1, b)
|
||||
|
||||
_sort(0, len(lst) - 1)
|
||||
return lst
|
||||
|
||||
|
||||
def quickSort3(lst):
|
||||
'''A rear recursive optimization version'''
|
||||
def partition(a,b):
|
||||
|
||||
def partition(a, b):
|
||||
pivot = lst[b]
|
||||
j = a-1
|
||||
for i in range(a,b):
|
||||
if lst[i]<=pivot:
|
||||
j+=1
|
||||
if i!=j: lst[i], lst[j] = lst[j], lst[i]
|
||||
lst[j+1],lst[b] = lst[b],lst[j+1]
|
||||
return j+1
|
||||
def _sort(a,b):
|
||||
while a<b:
|
||||
mid = (a+b)//2
|
||||
j = a - 1
|
||||
for i in range(a, b):
|
||||
if lst[i] <= pivot:
|
||||
j += 1
|
||||
if i != j: lst[i], lst[j] = lst[j], lst[i]
|
||||
lst[j + 1], lst[b] = lst[b], lst[j + 1]
|
||||
return j + 1
|
||||
|
||||
def _sort(a, b):
|
||||
while a < b:
|
||||
mid = (a + b) // 2
|
||||
# 三数取中值置于第一个作为 pivot
|
||||
if (lst[a]<lst[mid]) ^ (lst[b]<lst[mid]): lst[b],lst[mid] = lst[mid],lst[b] # lst[mid] 为中值
|
||||
if (lst[a]>lst[b]) ^ (lst[a]>lst[mid]): lst[a],lst[b] = lst[b],lst[a] # lst[b] 为中值
|
||||
i = partition(a,b)
|
||||
_sort(a,i-1)
|
||||
a = i+1
|
||||
_sort(0,len(lst)-1)
|
||||
if (lst[a] < lst[mid]) ^ (lst[b] < lst[mid]):
|
||||
lst[b], lst[mid] = lst[mid], lst[b] # lst[mid] 为中值
|
||||
if (lst[a] > lst[b]) ^ (lst[a] > lst[mid]):
|
||||
lst[a], lst[b] = lst[b], lst[a] # lst[b] 为中值
|
||||
i = partition(a, b)
|
||||
_sort(a, i - 1)
|
||||
a = i + 1
|
||||
|
||||
_sort(0, len(lst) - 1)
|
||||
return lst
|
||||
|
||||
|
||||
from time import time
|
||||
def timer(func,lst,n=100):
|
||||
|
||||
|
||||
def timer(func, lst, n=100):
|
||||
t = time()
|
||||
for i in range(n):func(lst)
|
||||
t = time()-t
|
||||
print('{}: {}s'.format(func.__name__,t))
|
||||
for i in range(n):
|
||||
func(lst)
|
||||
t = time() - t
|
||||
print('{}: {}s'.format(func.__name__, t))
|
||||
return t
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
from random import randint
|
||||
print('5000 items, repeat 100 times for each')
|
||||
lst = [randint(0,100) for i in range(5000)]
|
||||
timer(quickSort,lst.copy())
|
||||
timer(quickSort2,lst.copy())
|
||||
timer(quickSort3,lst.copy())
|
||||
lst = [randint(0, 100) for i in range(5000)]
|
||||
timer(quickSort, lst.copy())
|
||||
timer(quickSort2, lst.copy())
|
||||
timer(quickSort3, lst.copy())
|
||||
|
||||
lst = [randint(0,100) for i in range(15)]
|
||||
lst = [randint(0, 100) for i in range(15)]
|
||||
print(lst)
|
||||
print(quickSort(lst.copy()))
|
||||
print(quickSort2(lst.copy()))
|
||||
print(quickSort3(lst.copy()))
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user