数据结构之查找

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值