📅  最后修改于: 2023-12-03 15:26:09.673000             🧑  作者: Mango
哈希表(Hash Table),也叫散列表,是根据关键码值(Key Value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做哈希函数,存放记录的数组叫做哈希表。
哈希表的实现使用数组和链表的数据结构,它的操作可以分为插入、查找、删除等基本操作。哈希表的优点是查找速度快,时间复杂度通常为 O(1),是数组和链表等数据结构无法比拟的。
哈希函数是哈希表实现的关键,它将每个关键字映射到哈希表中的一个位置。一个好的哈希函数需要满足以下几个条件:
常用的哈希函数有以下几种:
直接定址法是最简单的哈希函数,它直接将关键字作为哈希值。例如,对于一个整数关键字,哈希函数可以是 $h(key)=key$。
直接定址法的缺点是它的散列性非常依赖关键字本身,如果关键字分布极其不均匀,容易产生冲突。
除留余数法是将关键字除以某个数,取余数作为哈希值。例如,对于一个整数关键字,哈希函数可以是 $h(key)=key % p$,其中 $p$ 是一个质数。
除留余数法实现简单,散列性较好,但不能使用长度与 $p$ 相近的关键字,否则容易导致冲突。
平方取中法是先将关键字平方,然后取中间的几位作为哈希值。例如,对于一个四位十进制数关键字 $6954$,哈希函数可以是 $h(key)=middle(6954^2)$,其中 $middle$ 是取中间两位的函数。
平方取中法较好地解决了直接定址法和除留余数法的缺点,但实现起来稍微麻烦一些。
随机数法是使用一个随机数当作哈希函数,例如,对于一个整数关键字,哈希函数可以是 $h(key)=random()$。随机函数需要足够随机,才能达到较好的散列效果。
随机数法实现简单,散列性好,但需要较大的空间存储随机数。
下面是一个简单的哈希表实现,包括哈希函数和基本操作:插入、查找、删除。
class Node:
def __init__(self, key, value):
self.key = key # 关键字
self.value = value # 值
self.next = None # 指向下一个节点
class HashTable:
def __init__(self, size=1000):
self.size = size # 哈希表大小
self.table = [None] * size # 哈希表数组
def _hash(self, key):
"""哈希函数:通过取余方法计算哈希值"""
return hash(key) % self.size
def put(self, key, value):
"""插入"""
h = self._hash(key)
if self.table[h] is None:
self.table[h] = Node(key, value)
return
node = self.table[h]
while node.next is not None:
node = node.next
node.next = Node(key, value)
def get(self, key):
"""查找"""
h = self._hash(key)
node = self.table[h]
while node is not None:
if node.key == key:
return node.value
node = node.next
return None
def remove(self, key):
"""删除"""
h = self._hash(key)
node = self.table[h]
if node is None:
return
if node.key == key:
self.table[h] = node.next
return
while node.next is not None:
if node.next.key == key:
node.next = node.next.next
return
node = node.next
哈希表是一种高效的数据结构,可用于快速查找数据。然而,哈希函数的实现是一门深奥的学问,有一些关键的问题需要解决,例如哈希值的分布均衡、冲突处理等。在实际应用中,需要根据具体情况选择哈希函数的适当实现,以达到最佳的效果。