哈希表 | 青训营 X 豆包MarsCode AI 刷题

62 阅读4分钟

哈希表(Hash Table)是一种高效的数据结构,用于实现快速的数据查找、插入和删除。其基本思想是通过将键(Key)映射到一个固定大小的数组索引(索引称为哈希值)来实现数据的快速访问。哈希表常用于需要快速查询的场景,例如数据库索引、缓存实现以及实现关联数组等。

哈希表的基本原理

哈希表使用哈希函数将输入的键映射到数组的一个索引位置。哈希函数将键转换为一个整数,这个整数再通过取模操作确定在数组中的位置。由于数组的大小是有限的,不同的键可能会被哈希到同一个索引位置,这种情况被称为“冲突”。解决冲突的方法有多种,常见的有开地址法和链表法。

哈希函数

哈希函数是哈希表的核心组件,它的质量直接影响哈希表的性能。一个好的哈希函数应具备以下特性:

  • 快速计算:计算哈希值的时间应尽可能快。
  • 随机性:不同的键应该均匀分布到哈希表中,以减少冲突。
  • 确定性:相同的键必须映射到相同的哈希值。

冲突解决策略

  1. 链表法:每个数组索引存储一个链表,当发生冲突时,将新的键值对追加到链表中。
  2. 开地址法:当发生冲突时,寻找下一个空闲的数组索引位置存储新的键值对。常用的探查方法有线性探查、二次探查和双重哈希。

哈希表的基本操作

哈希表的主要操作包括插入、查找和删除。以下是这些操作的详细描述:

  1. 插入(Insert):将键值对插入哈希表。如果键已经存在,则更新其值。
  2. 查找(Search):根据键查找对应的值。如果存在返回该值,否则返回空值。
  3. 删除(Delete):根据键删除对应的键值对。

哈希表的实现示例

下面是一个使用 Python 实现的简单哈希表,包括插入、查找和删除操作,以及冲突处理的策略(采用链表法)。

class HashNode:
    def __init__(self, key, value):
        self.key = key
        self.value = value
        self.next = None  # 用于处理冲突的链表节点


class HashTable:
    def __init__(self, size=10):
        self.size = size  # 哈希表大小
        self.table = [None] * self.size  # 初始化哈希表为大小为 size 的空列表

    def _hash_function(self, key):
        """计算哈希值的哈希函数"""
        return hash(key) % self.size

    def insert(self, key, value):
        """插入键值对"""
        index = self._hash_function(key)
        new_node = HashNode(key, value)

        # 处理冲突
        if self.table[index] is None:
            self.table[index] = new_node
        else:
            current = self.table[index]
            while True:
                if current.key == key:
                    current.value = value  # 更新值
                    return
                if current.next is None:
                    break
                current = current.next
            current.next = new_node  # 插入新节点

    def search(self, key):
        """查找键对应的值"""
        index = self._hash_function(key)
        current = self.table[index]

        while current is not None:
            if current.key == key:
                return current.value  # 找到键,返回值
            current = current.next  # 继续查找链表
        return None  # 未找到键

    def delete(self, key):
        """删除键值对"""
        index = self._hash_function(key)
        current = self.table[index]
        previous = None

        while current is not None:
            if current.key == key:
                if previous is None:
                    self.table[index] = current.next  # 删除头节点
                else:
                    previous.next = current.next  # 删除中间或尾节点
                return True  # 成功删除
            previous = current
            current = current.next
        return False  # 未找到键

    def display(self):
        """显示哈希表内容"""
        for index in range(self.size):
            current = self.table[index]
            if current:
                print(f"Index {index}: ", end="")
                while current:
                    print(f"({current.key}: {current.value}) -> ", end="")
                    current = current.next
                print("None")
            else:
                print(f"Index {index}: None")


# 使用示例
hash_table = HashTable()

# 插入键值对
hash_table.insert("apple", 10)
hash_table.insert("banana", 20)
hash_table.insert("orange", 30)
hash_table.insert("grape", 40)

# 显示哈希表内容
hash_table.display()

# 查找操作
print("Search for 'banana':", hash_table.search("banana"))  # 输出: 20
print("Search for 'kiwi':", hash_table.search("kiwi"))  # 输出: None

# 删除操作
hash_table.delete("banana")
print("After deleting 'banana':")
hash_table.display()  # banana 应该被删除

哈希表的性能分析

哈希表的时间复杂度如下:

  • 插入:平均情况下 (O(1)),最坏情况下 (O(n))(当所有元素都冲突时)。
  • 查找:平均情况下 (O(1)),最坏情况下 (O(n))。
  • 删除:平均情况下 (O(1)),最坏情况下 (O(n))。

哈希表的优缺点

优点

  1. 快速访问:哈希表可以在常数时间内进行插入、查找和删除操作。
  2. 灵活性:可以存储不同类型的数据,支持动态扩展。

缺点

  1. 内存使用:哈希表可能会浪费内存,尤其是在负载因子较低时(即存储的元素数量与哈希表大小的比率)。
  2. 冲突处理复杂:当发生大量冲突时,性能会显著下降,需要设计高效的冲突解决策略。

刷题示例

屏幕截图 2024-11-26 191454.png

总结

哈希表是一种非常实用的数据结构,广泛应用于各种软件系统中。通过有效地实现哈希函数和冲突处理机制,哈希表可以提供快速的数据访问能力。在实际应用中,选择合适的哈希表大小和冲突处理策略可以显著提升性能。