📜  使用哈希实现电话目录(1)

📅  最后修改于: 2023-12-03 15:22:23.081000             🧑  作者: Mango

使用哈希实现电话目录

什么是哈希?

哈希(Hash)是一种将任意大小的数据映射到固定大小的数据的方法。哈希表就是使用哈希技术实现的一种数据结构,它允许快速的插入、删除、查找数据。

哈希表的实现

使用哈希表实现电话目录,需要以下几个步骤:

  1. 定义一个桶数组,桶的数量通常选取为质数,如101、103等等。

  2. 将每个电话号码转换为一个哈希值,可以使用简单的取模运算来实现,如对电话号码取模101。

  3. 将哈希值作为索引,将电话号码存入相应的桶中。

  4. 对于哈希冲突,可以采用开放地址法、链表法等方式来解决。

开放地址法

开放地址法是一种解决哈希冲突的方法,它的思路是如果一个哈希值已经被占用了,就往后找一个空闲的位置,直到找到空闲位置为止。

线性探测

线性探测是最简单的开放地址法,它的步骤如下:

  1. 如果该位置已经被占用了,就顺序往后找下一个位置,直到找到一个空闲位置或者查找了整个桶数组。

  2. 如果整个桶数组都被查找了一遍,但是没有找到空闲位置,那么就认为哈希表已经满了。

二次探测

二次探测是一种改进的开放地址法,它的步骤如下:

  1. 如果该位置已经被占用了,就计算下一个探测点的位置,可以使用如下公式:$hash_i = (hash(key) + i^2) % tableSize$,其中i表示进行了几次探测。

  2. 如果所有的探测点都被占用,那么就认为哈希表已经满了。

链表法

链表法是另一种常用的解决哈希冲突的方法,它的思路是当多个键值映射到同一个位置时,将这些键值放在同一个链表中。

代码实现

下面是使用Python实现电话目录的示例代码,其中使用开放地址法进行哈希冲突的解决。

class PhoneBook:
    def __init__(self, size=101):
        self.size = size
        self.table = [None] * self.size

    def _hash(self, key):
        return hash(key) % self.size

    def insert(self, key, value):
        h = self._hash(key)
        i = 0
        while i < self.size and self.table[h] is not None:
            h = (h + 1) % self.size
            i += 1
        if i == self.size:
            raise Exception('Hash table is full')
        self.table[h] = (key, value)

    def search(self, key):
        h = self._hash(key)
        i = 0
        while i < self.size and self.table[h] is not None:
            if self.table[h][0] == key:
                return self.table[h][1]
            h = (h + 1) % self.size
            i += 1
        return None

    def delete(self, key):
        h = self._hash(key)
        i = 0
        while i < self.size and self.table[h] is not None:
            if self.table[h][0] == key:
                self.table[h] = None
                return
            h = (h + 1) % self.size
            i += 1
        raise KeyError(key)
总结

哈希表是一种高效的数据结构,可以用于实现电话目录、词频统计、缓存等等场景。在使用哈希表时,需要注意哈希冲突的解决方法以及哈希函数的选择。