⽤python实现⼀个redis的zt数据结构⽤了redis也有2年多了,常常感叹于redis的优美和精悍,⿇雀虽⼩五脏俱全。
最近⼿痒冒出⽤python在内存中实现⼀个zt数据结构的想法。
思路是这样的:
hash + sortedlist
其中hash⽤于使获取键值的复杂度变成O(1)
⽽⽤bict模块⼆分法作⽤于sortedlist实现其它操作O(logN)
下⾯上代码。
#coding=utf-8
from bict import bict_left,bict_right,insort
#定义节点
class SNode:
def __init__(lf,key=None, score=float('-inf'),next=None):
lf.key = key
lf.score = score
def __lt__(lf,other):
return lf.score < getattr(other,'score',other)
def __gt__(lf,other):#没定义__gt__的话会导致bict_right出问题,即使已经定义了__lt__
return lf.score > getattr(other,'score',other)
不可分割#定义数组,⽤bict维护顺序
class Slist(object):
def __init__(lf):
lf.key2node = {}
lf.card = 0
def findpos(lf, snode):
curpos = bict_derlist,snode)
while 1:
derlist[curpos].key==snode.key:
break
curpos += 1
return curpos
def inrt(lf,key,score):
if not isinstance(score,int):rai Exception('score must be integer')
跟我学英语视频教程
snode = (key)
if snode:
if score == snode.score:
return 0
derlist[lf.findpos(snode)]
snode.score = score
el:
lf.card += 1
snode = SNode(key=key,score=score)
lf.key2node[key] = snode
derlist, snode)
return 1
def delete(lf,key):
def delete(lf,key):
snode = (key)
if not snode:
return 0
lf.card -= 1
derlist[lf.findpos(snode)]
电台
del lf.key2node[key]
del snode
return 1
def arch(lf,key):
return (key)
class SortedSet:
def __init__(lf):
lf.slist = Slist()
def zadd(lf, key, score):
return lf.slist.inrt(key, score)
def zrem(lf, key):
return lf.slist.delete(key)
def zrank(lf, key):#score相同则按字典序
snode = lf.(key)
if not snode:
return None
return lf.slist.findpos(snode)
def zrevrank(lf, key):
ard - 1 - lf.zrank(key)
def zscore(lf, key):
snode = lf.(key)
return getattr(snode,'score',None)
def zcount(lf, start, end):
ol = derlist
return bict_left(ol,end+1) - bict_right(ol,start-1)
@property
def zcard(lf):
return lf.slist.card
def zrange(lf, start, end, withscores=Fal):#score相同则按字典序
nodes = derlist[start: end+1]
if not nodes:return []
if withscores:
return [(x.key, x.score) for x in nodes]
el:
return [x.key for x in nodes]
def zrevrange(lf, start, end, withscores=Fal):
card = lf.zcard
if end<0:
end = end + card
if start<0:sharky
start = start + card
nodes = derlist[max(card-end-1, 0): max(card-start, 0)][::-1] if not nodes:return []
if withscores:
return [(x.key, x.score) for x in nodes]
el:
federal funds ratereturn [x.key for x in nodes]
def zrangebyscore(lf, start, end, withscores=Fal):
def zrangebyscore(lf, start, end, withscores=Fal):
ol = derlist
nodes = ol[bict_left(ol, start):bict_right(ol, end)]
if not nodes:return []
if withscores:
return [(x.key, x.score) for x in nodes]
el:
return [x.key for x in nodes]
def zrevrangebyscore(lf, end, start, withscores=Fal):
angebyscore(start, end, withscores)[::-1]
def zincrby(lf, key):
snode = lf.(key)
if not snode:
return lf.zadd(key, 1)
score = snode.score
<(key)
return lf.zadd(key, score+1)
import contextlib
import time
timeobj = {}
class timetrace:
@tmanager
def mark(lf,name):
t = time.time()
yield
timeobj[name] = time.time() - t
def stat(lf):
print '---------benchmark(100000 requests)---------'
for k,v in timeobj.iteritems():
print '{} {}s'.format(k,v)
tt = timetrace()
if __name__ == '__main__':
s = SortedSet()
s.zadd('kzc',17)
s.zadd('a',1)
s.zadd('b',2)
三星广告背景音乐
s.zadd('c',2)
s.zadd('d',6)
s.zadd('hello',18)
s.zadd('world',18)
s.zincrby('kzc')
print 'kzc score',s.zscore('kzc')
print 'kzc rank',s.zrank('kzc')
print 'kzc revrank',s.zrevrank('kzc')
print 'zcount(1,20)',s.zcount(1,20)
print 'zrange(2,4,withscores=True)',s.zrange(2,4,withscores=True)
print 'zrangebyscore(1,5,withscores=True)',s.zrangebyscore(1,5,withscores=True) print 'zrem("c")',s.zrem('c')
print 'zrangebyscore(1,5,withscores=True)',s.zrangebyscore(1,5,withscores=True) print 'zcard',s.zcard
print 's.zadd("c",7)',s.zadd('c',7)
print 'zcard',s.zcard
print 'zrevrange all',s.zrevrange(0,-1,withscores=True)
#benchmark
import random
keys = [str(x) for x in range(0,100000)]
values = range(0,100000)raj
random.shuffle(keys)speak
random.shuffle(keys)
with tt.mark('zadd'):
map(lambda x,y:s.zadd(x,y),keys,values) with tt.mark('zscore'):
map(s.zscore,keys)
with tt.mark('zrank'):
ank,keys)
tt.stat()音译汉
结果截图如下: