数据结构与算法之数据结构 哈希表面试高频 冲突处理 / 扩容

数据结构与算法阿木 发布于 3 天前 1 次阅读


摘要:

哈希表是一种基于哈希函数的数据结构,它能够以接近常数的时间复杂度进行插入、删除和查找操作。哈希表在实际应用中可能会遇到冲突问题,即不同的键映射到同一个哈希值。本文将深入探讨哈希表的冲突处理和扩容策略,并通过代码示例来展示这些技术的实现。

一、

哈希表是一种非常高效的数据结构,广泛应用于各种场景,如缓存、数据库索引、集合等。哈希表的核心思想是将键映射到表中的一个位置,从而实现快速访问。由于哈希函数的特性,冲突是不可避免的。如何有效地处理冲突和进行扩容是哈希表设计中的关键问题。

二、哈希表的基本原理

哈希表由一个数组和一个哈希函数组成。数组的大小称为哈希表的容量,通常是一个质数,以减少冲突的概率。哈希函数将键映射到数组中的一个索引位置。

python

class HashTable:


def __init__(self, capacity=10):


self.capacity = capacity


self.table = [None] self.capacity


self.size = 0

def hash_function(self, key):


return hash(key) % self.capacity


三、冲突处理策略

冲突处理是哈希表设计中的关键部分。以下是一些常见的冲突处理策略:

1. 链地址法

链地址法是将所有具有相同哈希值的元素存储在同一个链表中。当发生冲突时,将新元素添加到链表的末尾。

python

class HashTable:


def __init__(self, capacity=10):


self.capacity = capacity


self.table = [None] self.capacity


self.size = 0

def hash_function(self, key):


return hash(key) % self.capacity

def insert(self, key, value):


index = self.hash_function(key)


if self.table[index] is None:


self.table[index] = []


for pair in self.table[index]:


if pair[0] == key:


pair[1] = value


return


self.table[index].append([key, value])


self.size += 1

def find(self, key):


index = self.hash_function(key)


if self.table[index] is not None:


for pair in self.table[index]:


if pair[0] == key:


return pair[1]


return None


2. 开放寻址法

开放寻址法是在发生冲突时,继续在哈希表中寻找下一个空槽位,直到找到为止。

python

class HashTable:


def __init__(self, capacity=10):


self.capacity = capacity


self.table = [None] self.capacity


self.size = 0

def hash_function(self, key):


return hash(key) % self.capacity

def insert(self, key, value):


index = self.hash_function(key)


while self.table[index] is not None:


index = (index + 1) % self.capacity


self.table[index] = [key, value]


self.size += 1

def find(self, key):


index = self.hash_function(key)


while self.table[index] is not None:


if self.table[index][0] == key:


return self.table[index][1]


index = (index + 1) % self.capacity


return None


3. 双散列法

双散列法使用两个哈希函数来处理冲突。当第一个哈希函数产生冲突时,使用第二个哈希函数来计算下一个索引。

python

class HashTable:


def __init__(self, capacity=10):


self.capacity = capacity


self.table = [None] self.capacity


self.size = 0

def hash_function1(self, key):


return hash(key) % self.capacity

def hash_function2(self, key):


return 1 + (hash(key) % (self.capacity - 1))

def insert(self, key, value):


index = self.hash_function1(key)


while self.table[index] is not None:


if self.table[index][0] == key:


self.table[index][1] = value


return


index = (index + self.hash_function2(key)) % self.capacity


self.table[index] = [key, value]


self.size += 1

def find(self, key):


index = self.hash_function1(key)


while self.table[index] is not None:


if self.table[index][0] == key:


return self.table[index][1]


index = (index + self.hash_function2(key)) % self.capacity


return None


四、扩容策略

随着哈希表中元素的增多,冲突的概率也会增加。为了维持哈希表的性能,需要定期进行扩容。以下是一些常见的扩容策略:

1. 线性扩容

线性扩容是指每次扩容时,将哈希表的容量翻倍。

python

class HashTable:


def __init__(self, capacity=10):


self.capacity = capacity


self.table = [None] self.capacity


self.size = 0

def hash_function(self, key):


return hash(key) % self.capacity

def insert(self, key, value):


if self.size >= self.capacity / 2:


self.resize(self.capacity 2)


index = self.hash_function(key)


if self.table[index] is None:


self.table[index] = []


for pair in self.table[index]:


if pair[0] == key:


pair[1] = value


return


self.table[index].append([key, value])


self.size += 1

def resize(self, new_capacity):


old_table = self.table


self.capacity = new_capacity


self.table = [None] self.capacity


self.size = 0


for pair in old_table:


if pair is not None:


for key, value in pair:


self.insert(key, value)


2. 拉链法扩容

拉链法扩容是指每次扩容时,将所有元素重新散列到新的哈希表中。

python

class HashTable:


def __init__(self, capacity=10):


self.capacity = capacity


self.table = [None] self.capacity


self.size = 0

def hash_function(self, key):


return hash(key) % self.capacity

def insert(self, key, value):


if self.size >= self.capacity / 2:


self.resize(self.capacity 2)


index = self.hash_function(key)


if self.table[index] is None:


self.table[index] = []


for pair in self.table[index]:


if pair[0] == key:


pair[1] = value


return


self.table[index].append([key, value])


self.size += 1

def resize(self, new_capacity):


old_table = self.table


self.capacity = new_capacity


self.table = [None] self.capacity


self.size = 0


for pair in old_table:


if pair is not None:


for key, value in pair:


self.insert(key, value)


五、总结

哈希表是一种高效的数据结构,但在实际应用中需要处理冲突和进行扩容。本文介绍了链地址法、开放寻址法、双散列法等冲突处理策略,以及线性扩容和拉链法扩容策略。通过代码示例,展示了这些技术的实现。在实际应用中,选择合适的冲突处理和扩容策略对于维持哈希表的性能至关重要。