数据结构之查找

来源:互联网 发布:linux 系统启动脚本 编辑:程序博客网 时间:2024/05/29 05:03

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)

关于getitemsetitem的用法:
python四个魔法方法len,getitem,setitem,delitem