前言
这周缺席了两天,因此后续的学习量要增加。
(本文图片来自算法村)
Hash
哈希(Hash)也称为散列,就是把任意长度的输入,通过散列算法,变成固定长度的输出,这个输出值就是散列值。
例如,当我们把1到15这写数字存入大小是7的Hash表中时,对数字进行取模,随后存入。
但是,我们出现了一个问题:当我们试图访问这些数字的时候会发现,很多数字被后来的数字给覆盖了。
这种两个不同输入值,根据同一个散列函数计算出的散列值相同的现象叫做碰撞。
怎样解决呢?
常见方法:开放定址法、链地址法、再哈希法、建立公共溢出区。
下面介绍前两种常见方法。
开放定址法
一旦发生冲突,就寻找下一个空的链表地址。只要散列表足够大,就会存在这样空的散列地址,并进行存入操作。
如上图所示,将8、9这些原本可能冲突的值分别存入了Hash表中的空位置,避免了碰撞。
链地址法
另一种方法在思路上更为直接:我们对于每个冲突的索引值,将这个单元作为头节点创建链表,把发生冲突的值以链表的形式存放在这个链表的尾部。
在操作中,可能是长这样的:数组长度为2的n次幂,在size不超过一定比例的前提下(因为超过一定比例会采取扩容来规避碰撞),找到数组下标,如果为空就存入,如果不为空就判断key值是否一样;如果key一样就替换,如果不一样就以链表的形式存入链表。
队列
队列是先进先出(FIFO)的一种数据结构。
链表有两种实现形式:基于数组&基于链表。
以下是Python中基于数组手搓队列的代码:
class Queue:
"""队列"""
def __init__(self):
self.items = []
def is_empty(self):
return self.items == []
def enqueue(self, item):
"""进队列"""
self.items.insert(0, item)
def dequeue(self):
"""出队列"""
return self.items.pop()
def size(self):
"""返回大小"""
return len(self.items)