1、搜索
最简单的使用 in 运算符
>>> 15 in [3,5,2,4,1]
False
2、顺序查找:复杂度是 O(n)
试想,当查找的项目不存在列表中时,无序查找的话最好、最差、平均情况都是n次,但有序查找就不一样了,最好的情况是1次,最差n次,平均n/2次对吧。
3、二分查找:复杂度是 O( log^n )
def binarySearch(alist, item):
if len(alist) == 0:
return False
else:
midpoint = len(alist)//2
if alist[midpoint]==item:
return True
else:
if item<alist[midpoint]:
return binarySearch(alist[:midpoint],item)
else:
return binarySearch(alist[midpoint+1:],item)
testlist = [0, 1, 2, 8, 13, 17, 19, 32, 42,]
print(binarySearch(testlist, 3))
这里调用了递归。有一个疑问,当查找的结果不存在时,则必然最后一步查找是一个元素的列表,那么midpoint = 0,alist[:0],貌似这个定义是错误的。怎么解?
4.哈希查找
4.1 哈希查找的本质是先将数据映射成它的哈希值。哈希查找的核心是构造一个哈希函数,它将原来直观、整洁的数据映射为看上去似乎是随机的一些整数。
1)余数法、分组求和/tablesize、平方取中/tablesize。哈希表的初始大小是任意的,但是重要的是,大小是质数,使得冲突解决算法可以尽可能高效。
哈希表的大小取决于一组质数,原因是在hash函数中,你要用这些质数来做模运算(%).而分析发现,如果不是用质数来做模运算的话,很多生活中的数据分布,会集中在某些点上。所以这里最后采用了质数做模的除数。因为用质数做了模的除数,自然存储空间的大小也用质数了。因为模完之后,数据是在[0-所选质数)之间。
2)对于字符串,可以根据其ascii码累加,并以其位置值作为权重因子,除以tablesize来作为散列值。
4.2 解决冲突
1)线性探测的开放寻址技术:从原始哈希值位置开始,然后以顺序方式移动槽,直到遇到第一个空槽,为避免聚集,可以将探头加3。
2)线性探测思想的一个变种称为二次探测。代替使用常量 “跳过” 值,将散列值递增 1,3,5,7,9, 依此类推。这意味着如果第一哈希值是 h,直到找到空槽,则连续值是h + 1,h + 4,h + 9,h + 16,等等。
class HashTable():
def __init__(self):
self.size = 11
self.slots = [None] * self.size #保存key值 [None, None, None, None, None, None, None, None, None, None, None]
self.data = [None] * self.size #保存对应value值
def hashfunction(self, key):
return key % self.size #余数法
def rehash(self, oldhash):
return (oldhash + 1) % self.size
def put(self,key,val):
hashvalue = self.hashfunction(key) #根据哈希函数求出的散列值
if self.slots[hashvalue] ==None:
self.slots[hashvalue] = key
self.data[hashvalue] = val
else:
if self.slots[hashvalue] == key:
self.data[hashvalue] = val # replace
else:
nextslot = self.rehash(hashvalue)
while self.slots [nextslot] != None and self.slots[nextslot] !=key: #解决冲突线性寻址的三种情况,not None,not key
nextslot = self.rehash(nextslot)
if self.slots[nextslot] == None: #寻找到的槽为空
self.slots[nextslot] = key
self.data[nextslot] = val
else: #寻找到的槽key值相等
self.data[nextslot] = val # replace
def get(self, key):
startslot = self.hashfunction(key)
val = None
stop = False
found = False
position = startslot
while self.slots[position] != None and not found and not stop:
if self.slots[position] == key:
found = True
val = self.data[position]
else:
position = self.rehash(position)
if position == startslot:
stop = True
return val
def __getitem__(self, key):
return self.get(key)
def __setitem__(self, key, val):
self.put(key, val)
H = HashTable()
H[54] = 'cat'
print(H.slots)
关于getitem和setitem的用法:
python四个魔法方法len,getitem,setitem,delitem