哈希查找算法(Hash Lookup Algorithm),也称为哈希表(Hash Table),是一种基于哈希函数实现的数据结构,常常用于解决高效查找问题。
在哈希查找算法中,我们首先需要将要查找的关键字使用哈希函数转化为一个整数,然后将其作为数组下标,将数据存储在数组中。在查找时,我们同样使用哈希函数将关键字转化为对应的整数值,然后在数组中查找所对应的数据。该算法的查找效率非常高,时间复杂度近似为O(1)。
下面是哈希查找算法的一些使用方法:
哈希函数的设计
哈希函数是哈希算法的核心,它将任意长度的输入(关键字)映射到固定长度的输出(整数)。好的哈希函数应该能够将输入散列到尽量均匀的输出空间中,这样可以减少冲突(相同哈希值的关键字),提高查找效率。常用的哈希函数有以下几种:
- 直接寻址法:将关键字作为数组下标,直接定位存储位置。这种方法适用于关键字较小且空间充足的场景。
hash(key) = key
- 取模法:将关键字除以一个质数,取余数作为哈希值。质数的选择应该尽量大,这样可以减小哈希冲突的概率。
hash(key) = key % n
- 平方取中法:将关键字平方后取其中几位作为哈希值。
hash(key) = (key * key) / 100 % n
哈希表的实现
哈希表通常采用数组来实现,同时需要一个哈希函数和一个解决冲突的方法。解决冲突的方法有很多种,其中最常用的是链地址法(Chaining)和开放地址法(Open Addressing)。
链地址法
链地址法是将哈希表的每个位置设置为一个链表,哈希冲突的关键字会被插入到链表中。链地址法的代码实现比较简单:
class Node:
def __init__(self, key, value):
self.key = key
self.value = value
self.next = None
class HashTable:
def __init__(self, capacity):
self.capacity = capacity
self.table = [None] * self.capacity
def put(self, key, value):
index = hash(key) % self.capacity
node = self.table[index]
while node:
if node.key == key:
node.value = value
return
node = node.next
node = Node(key, value)
node.next = self.table[index]
self.table[index] = node
def get(self, key):
index = hash(key) % self.capacity
node = self.table[index]
while node:
if node.key == key:
return node.value
node = node.next
return None
开放地址法
开放地址法是在哈希表中从哈希值对应的位置出发查找空闲的位置,直到找到一个空的位置来插入关键字或者找到对应的关键字,这样就可以实现哈希冲突的解决。开放地址法的代码实现如下:
class HashTable:
def __init__(self, capacity):
self.capacity = capacity
self.keys = [None] * self.capacity
self.values = [None] * self.capacity
def put(self, key, value):
index = hash(key) % self.capacity
while self.keys[index]:
if self.keys[index] == key:
self.values[index] = value
return
index = (index + 1) % self.capacity
self.keys[index] = key
self.values[index] = value
def get(self, key):
index = hash(key) % self.capacity
while self.keys[index]:
if self.keys[index] == key:
return self.values[index]
index = (index + 1) % self.capacity
return None
示例说明
假设我们要实现一个电话号码簿,每个联系人有姓名和电话号码两个属性。我们使用哈希表作为数据结构,将联系人的姓名作为关键字。
链地址法
首先定义 Node 类作为链表节点的数据结构,然后定义 HashTable 类作为哈希表的数据结构。我们使用链地址法解决冲突,即将哈希表中每个位置设为一个链表。
class Node:
def __init__(self, key, value):
self.key = key
self.value = value
self.next = None
class HashTable:
def __init__(self, capacity):
self.capacity = capacity
self.table = [None] * self.capacity
def put(self, key, value):
index = hash(key) % self.capacity
node = self.table[index]
while node:
if node.key == key:
node.value = value
return
node = node.next
node = Node(key, value)
node.next = self.table[index]
self.table[index] = node
def get(self, key):
index = hash(key) % self.capacity
node = self.table[index]
while node:
if node.key == key:
return node.value
node = node.next
return None
然后我们可以使用 HaahTable 类创建一个电话号码簿并存储联系人信息:
phone_book = HashTable(100)
phone_book.put("Alice", "1234567")
phone_book.put("Bob", "2345678")
phone_book.put("Charlie", "3456789")
接下来可以通过姓名查找电话号码:
print(phone_book.get("Alice")) # output: 1234567
print(phone_book.get("Bob")) # output: 2345678
print(phone_book.get("David")) # output: None
开放地址法
我们还可以使用开放地址法实现电话号码簿这个例子。首先我们定义 HashTable 类作为哈希表的数据结构,使用两个数组分别存储关键字和相应的值:
class HashTable:
def __init__(self, capacity):
self.capacity = capacity
self.keys = [None] * self.capacity
self.values = [None] * self.capacity
def put(self, key, value):
index = hash(key) % self.capacity
while self.keys[index]:
if self.keys[index] == key:
self.values[index] = value
return
index = (index + 1) % self.capacity
self.keys[index] = key
self.values[index] = value
def get(self, key):
index = hash(key) % self.capacity
while self.keys[index]:
if self.keys[index] == key:
return self.values[index]
index = (index + 1) % self.capacity
return None
然后我们可以使用 HaahTable 类创建一个电话号码簿并存储联系人信息:
phone_book = HashTable(100)
phone_book.put("Alice", "1234567")
phone_book.put("Bob", "2345678")
phone_book.put("Charlie", "3456789")
接下来可以通过姓名查找电话号码:
print(phone_book.get("Alice")) # output: 1234567
print(phone_book.get("Bob")) # output: 2345678
print(phone_book.get("David")) # output: None
以上是哈希查找算法的详细讲解,希望对你有所帮助。