实现Hash表(二)----处理index冲突问题

配合前置文章食用更佳,传送门如下:
实现Hash表(一)----手写一个简单hash表

问题描述

在上一篇文章中,我们已经实现了自己的hash表结构,但是当两个key映射同一个value时,就会发生冲突,我们应该对冲突进行处理,使得发生冲突时也可以正常添加和删除。

解决办法

这里我们采用最简单的方法,实际算法可能要比这个复杂得多,但是原理是相同的

解决办法:当冲突发生的时候,向后遍历,找到第一个为None的位置,返回对应的index

所以在计算index的时候,会遇到如下几种情况:

  1. index所在位置为None,无冲突,可以直接返回
  2. index所在位置已经被占据,向后遍历,遇到key和所要插入的key相同的项,返回对应的index
  3. index所在位置已经被占据,向后遍历,遇到第一个None,返回对应的index
  4. index所在位置已经被占据,向后遍历,但是超出了最大长度,这时需要从头继续遍历

具体参照下面的get_valid_index的实现

python的实现

MAX_HASH_TABLE_SIZE = 4096


def get_index(data_list, a_string):
    # 存储hash值
    result = 0
    for a_character in a_string:
        # 获取ASCII码
        a_number = ord(a_character)
        # 更新hash值
        result += a_number
    # 通过取余数获取索引值
    list_index = result % len(data_list)
    return list_index

def get_valid_index(data_list, a_string):
    """
    :param data_list:
    :param a_string: 输入的key
    :return: 处理冲突后的索引
    当有冲突发生时(也就是两个字符串对应一个key),先映射,如果有值了那个位置
    就向后寻找第一个非none值对应的索引,对其进行更新
    """
    index = get_index(data_list, a_string)
    while True:
        key_value = data_list[index]
        if key_value is None:
            return index
        key, value = key_value[0], key_value[1]
        if key == a_string:
            return index
        index += 1
        if index == len(data_list):
            index = 0
        
 class HashTable:
    """
        处理过冲突的hashtable
        两个key对应一个索引,也可以正常运行
    """
    def __init__(self, max_size=MAX_HASH_TABLE_SIZE):
        self.data_list = [None] * max_size

    def insert(self, key, value):
        # 1. Find the index for the key using get_valid_index
        index = get_valid_index(self.data_list, key)
        # 2. Store the key-value pair at the right index
        self.data_list[index] = (key, value)

    def find(self, key):
        # 1. Find the index for the key using get_valid_index
        index = get_valid_index(self.data_list, key)
        # 2. Retrieve the data stored at the index
        kv = self.data_list[index]
        # 3. Return the value if found, else return None
        return None if kv is None else kv[1]

    def update(self, key, value):
        # 1. Find the index for the key using get_valid_index
        index = get_valid_index(self.data_list, key)
        # 2. Store the new key-value pair at the right index
        self.data_list[index] = (key, value)

    def list_all(self):
        # 1. Extract the key from each key-value pair
        return [kv[0] for kv in self.data_list if kv is not None]
    
if __name__ == '__main__':  
    # listen和silent是冲突的,计算出来对应的index都为655
    # silent后插入,索引会变为656
    # Create a new hash table
    table = HashTable()
    # Insert a value
    table.insert('listen', 99)
    # Check the value
    print(table.find('listen') == 99)
    # Insert a colliding key
    table.insert('silent', 200)
    # Check the new and old keys
    print(table.find('listen') == 99 and table.find('silent') == 200)
    # Update a key
    table.insert('listen', 101)
    # Check the value
    print(table.find('listen') == 101)
    print(table.list_all() == ['listen', 'silent'])

总结

我们的hash表变得更完善了,接下来,让我们用我们已经实现的hash表来实现python中的字典吧~

传送门:实现Hash表(三)----实现python中的字典

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值