Python Hash Table 散列表

用于存储 key 对应的 value,给定 key,能够在非常快速的时间内找到 value。

设计一个散列函数,计算出关键字 key 对应的函数值 hashcode,作为数据对象 value 的存储地址。对某个关键字进行查找时,通过散列函数得到地址(或者是array的索引),通过索引访问数组直接得到这个 key 对应的 value,实现 O(1) 的时间复杂度。需要解决哈希冲突(Collision)的问题:即两个关键字映射到同一地址。一种解决办法是在产生冲突的地方使用链表存储,会带来新的问题就是如何确定 key 对应的 value 是链表中的哪个,所以这种情况下链表中不仅要存储 value,也要存储 key,也就是需要有两个 field,既存储 key,也存储 value

如果同一个 key 要插入不同的 value,有几种解决方式:一种是新插入的总是覆盖之前的 value,一种是允许一个key存在多个value,查找时随机返回一个 value,或者使用 find_all 返回所有 value

填充因子:n/N,已填充(已有的 key 的数量)/总空间;当填充因子变大时,会失去常数时间的效率,所以需要 resize:遍历原来的哈希表,re-hash 所有的 key,再把 value 存到新的哈希表的对应位置。当填充因子变小时,也需要 resize 释放内存

散列方法的存储对关键字是随机的,不适用于顺序查找关键字,不适用于最大/最小值查找或范围查找

散列函数的设计

散列函数最好计算高效,且映射之后对应的地址空间最好分布均匀以减少冲突。举例:

  • 数字:取模;平方取中法;折叠法(把数字拆分再相加)
  • 一个比较好的方法:hash_code(key) = (((a*key + b) mod p) mod N);p是一个远大于N 的素数(促进均匀分布),N是存储空间的长度(数组的长度)
  • 字符:ASCII 码加和再取模(很多冲突)
  • 一个比较好的方法(最终的 hashcode 取决于每个字符):

def hash_code(string_a, N):

hash_val = 0

for i in range(len(string_a)):

hash_val = (127 * hash_val + string_a[i]) % 16908799

return hash_val % N

哈希冲突

上面已经说了什么是哈希冲突,这里说一下处理哈希冲突的常用方法:

  • 线性探测法:发生冲突后,向前寻找一个空位来存储。注意删除操作应当将右侧所有相邻的键值对重新插入散列表中
  • 拉链法:在发生冲突的位置使用链表存储

这两种方法存储的时候都要同时存储 key 和 value,这样查找的时候才知道是否命中对应的key

主要功能实现:

使用拉链法解决哈希冲突;假设 key 是数字;如果同一个 key 插入不同的 value,则总是覆盖。

class listNode:

def __init__(self, key, value):

self.key = key

self.value = value

self.next = None

class HashTable:

def __init__(self,N):

self.size = N

self.table = [None] * N

hash_code(key) — 计算 key 的哈希值:参考上面提到的对应数字和字符串的散列方法

insert(key, value) — 在哈希表中插入新的 key 及其对应的 value

def insert(self, key, value):

index = self.hash_code(key)

head = self.table[index]

if not head: # 如果哈希表对应位置还是空的

self.table[index] = listNode(key, value)

else:

while head.next:

head = head.next

head.next = listNode(key, value)

find(key) — 寻找 key 对应的 value

def find(self, key):

index = self.hash_code(key)

head = self.table[index]

if not head:

return None

else:

while head:

if head.key == key:

return head.value

head = head.next

return None

remove(key) — 从哈希表中删除一个 key 及其对应的 value

def remove(self, key):

index = self.hash_code(key)

head = self.table[index]

if not head:

return None

else:

prev = None

while head:

if head.key == key:

next_node = head.next

if prev:

prev.next = next_node

return head.value

else:

self.table[index] = head.next

return head.value

else:

prev = head

head = head.next

return None

以上是 Python Hash Table 散列表 的全部内容, 来源链接: utcz.com/z/264544.html

回到顶部