抽象数据类型 “映射” :ADT Map
字典,通过保存key-data键值对的数据类型。 ADT Map的结构是键值关联的无序集合。其中关键码key具有唯一性,通过关键码可以唯一确定一个数据值。 通过散列表构造Map。
class HashTable:
def __init__(self):
self.size=11 #可以任意设置,但为了便于求解,应该设为素数
self.slots=[None]*self.size
self.data=[None]*self.size
#定义散列函数
def hashfunction(self,key):
return key%self.size
#定义冲突解决方法,简单线性加一
def rehash(self,oldhash):
return (oldhash+1)%self.size
def put(self,key,data):
hashvalue=self.hashfunction(key)
#key不存在
if self.slots[hashvalue] == None:
self.slots[hashvalue] = key
self.data[hashvalue] = data
#key已存在
else:
#未发生冲突
if self.slots[hashvalue] == key:
self.data[hashvalue] == data
else: #发生散列冲突
nextslot=self.rehash(hashvalue)
while self.slots[nextslot] !=None and self.slots[nextslot] !=key:
nextslot=self.rehash(nextslot)
if self.slots[nextslot] == None:
self.slots[nextslot]=key
self.data[nextslot]=data
else:
self.data[nextslot]=data
def get(self,key):
startslot=self.hashfunction(key)
pos=startslot
#空槽时则表示找不到key
while self.slots[pos]!=None:
if self.slots[pos]==key: #找到key
return self.data[pos]
else:
pos=self.rehash(pos) #没找到key,找下一个
if pos==startslot: #回到起点表示没找到key
return None
return None
#通过设置__getitem__和__setitem__就可以实现形如H[key]的取值和赋值
def __getitem__(self,key):
return self.get(key)
def __setitem__(self,key,data):
self.put(key,data)
if __name__==__main__:
H=HashTable()
H[1]=cat
H[5]=piajun
print(H[1])
print(H[5])
print(H[2])
输出
cat piajun None
散列在最好的情况下(无冲突),可以提供O(1)时间复杂度的查找性能。 评估散列冲突的最重要信息为负载因子λ,负载因子表示散列表的空间使用程度,一般来说:λ越小,散列冲突概率越小,数据项通常能够保存在自己所属的散列槽中;λ越大,冲突概率会越大,需要通过更多的比较来找到空槽;如果采用数据链,则意味着每条数据链上的数据项增多。
如果采用线性探测(依次往后找空槽)的开放定址法来解决冲突,则λ在0~1之间,
-
成功的查找,平均比对次数为 1 2 ( 1 + 1 1 − λ ) frac{1}{2}(1+frac{1}{1-lambda}) 21(1+1−λ1) 不成功的查找,平均比对次数为 1 2 ( 1 + ( 1 1 − λ ) 2 ) frac{1}{2}(1+(frac{1}{1-lambda})^2) 21(1+(1−λ1)2)
如果采用数据链来解决冲突(λ可大于1),
-
成功的查找,平均比对次数为 1 + λ 2 1+frac{lambda}{2} 1+2λ 不成功的查找,平均比对次数为λ
下一篇:
C语言程序输出水仙花数
