Map的python实现

概念

Python中的Dict是一种使用最为普遍的数据结构,特别是数据之间具有关联关系时。上一博文提到了hash function和hash table的概念,现在来用代码实现HashTable。
我们通过两个list来分别存储key和value,这就要求两个list的大小一致,在对应的index上分别存储key和value。实现HashTable最重要的两个方法是set和get方法,如果通过Class来实现,则需要实现特殊方法__setitem__和__getitem__。这样就可以通过索引来取值。

构造方法

class HashTable:
    def __init__(self):
        self.size = 11
        self.slots = [None] * self.size
        self.data = [None] * self.size

确定一个HashTable的长度,并且存储key(slots)和value(data)的list也保持大小一致,且都初始化为None。

hash_function和rehash方法

    def hash_function(self, key, size):
        return key % size

    def rehash(self, old_hash, size):
        return (old_hash + 1) % size

通过hash_function方法确定key在hash table中的索引位置,通过rehash消除collision(不同的key经过hash function计算得到相同的index)。

set方法

    def set(self, key, value):
        hash_value = self.hash_function(key, len(self.slots))
        if self.slots[hash_value] is None:
            self.slots[hash_value] = key
            self.data[hash_value] = value
        else:
            if self.slots[hash_value] == key:
                self.data[hash_value] = value
            else:
                next_slot = self.rehash(hash_value, len(self.slots))
                while self.slots[next_slot] is not None and self.slots[
                    next_slot] != key:
                    next_slot = self.rehash(next_slot, len(self.slots))
                if self.slots[next_slot] is None:
                    self.slots[next_slot] = key
                    self.data[next_slot] = value
                else:
                    self.data[next_slot] = value

set方法的逻辑是:先通过hash function计算key的hash值,然后在保存key的slots(list)中查找对应位置的值是否存在,若不存在,则在该位置保存key,在data(list)中保存key对应的value。
若在slots对应的位置处恰好为key,则update其value。反之,若在slots对应的位置处不为key,则说明发生了collision(数据冲突),那么我们通过rehash方法继续hash,找到一个空余的位置,将该键值对(key和value)放入该位置或仅更新其value。

get方法

    def get(self, key):
        start_slot = self.hash_function(key, len(self.slots))
        position = start_slot
        data = None
        while self.slots[position] is not None:
            if self.slots[position] == key:
                data = self.data[position]
                break
            else:
                position = self.rehash(position, len(self.slots))
                if position == start_slot:
                    break
        return data

get方法较为简单,也是先获取hash值,然后查找slots在该hash值处所对应的值是否存在,若存在,则判断保存的key是否和要查找的key相等,若相等则返回该值,若不相等则说明发生collision,则使用rehash继续查找。记住,rehash方法必须有一个判断机制,用以判断是否遍历完整个hash table(循环一圈,回到初次hash值)。

__setitem__和__getitem__方法 ##

    def __getitem__(self, key):
        return self.get(key)

    def __setitem__(self, key, value):
        self.put(key, value)

这两个方法主要是类似Pyhton字典中的set和get语法,如dic[key] = value。

总结:上述实践仅仅是一个简单的demo。实际对应hash table的大小,hash function的实现有各个各样的方法,在这里仅起到一个抛砖引玉的作用。

猜你喜欢

转载自www.cnblogs.com/jeffrey-yang/p/9863277.html