哈希表(hash table)---python实现


哈希表(基本概念)

哈希表(hash table,又称散列表)是一种数据集,其中数据项的存储方式尤其是有利于将来快速的查找定位。

散列表的每一个存储位置,成为槽,可以用来保存数据项,每个槽有一个唯一的名称。
在这里插入图片描述

实现从数据项到存储名称的转换的,称为散列函数(哈希函数)
有一种常见的散列方法是‘求余数’,将数据项厨艺散列表的大小,得到的余数作为槽号。
不过这很明显会存在一个问题,要保存的数据需要存到同一个槽中,会产生冲突。
完美散列函数;给定一组数据项,如果一个散列函数能把每个数据项都映射到不同的槽中,那么这个散列函数就称为‘完美散列函数’。
完美散列函数应用:
数据的一致性校验;(压缩性、易计算性、抗修改性、抗冲突性)
散列函数:
MD5、SHA
python的散列函数库hashlib;自带MD5和SHA系列的散列函数。
包括了md5 / sha1 / sha224 等六种散列函数。

>>> import hashlib
>>> m = hashlib.md5('hello'.encode('utf-8')).hexdigest()
>>> m
'5d41402abc4b2a76b9719d911017c592'

散列函数的最酷应用;
区块链技术

冲突解决:数据项链和线性探测

数据项链

我们知道数组的特点是寻址容易,插入和删除数组困难。而链表的特点是寻址困难,插入和删除数据容易。
可以看到哈希表的上面是数组,数组的每个成员包括一个指针,指向一个链表的头节点,当然链表可能为空,也可能链接多个节点。
在这里插入图片描述

我们存储键值对(key-value pair)的方式主要依靠键的特征,通过键的哈希值找到对应的数组下标,然后将其键值对添加到对应的链表中,寻找元素时,也是根据其键的哈希值,找到特定链表其对应的值。

我们可以对比python中的字典,字典是一种可以保存key- value键值对的数据类型,这种键值关联的方法称作‘映射Map’。

  • 关键码具有唯一性
  • 通过关键码可以唯一确定一个数据值

哈希表支持的操作:

  • add(key, val):将key-value关联对加入映射中,如果key已存在,将val替换旧关联值;
  • get(key):给定key,返回关联的数据值,如果不存在,返回None;
  • len( ) 返回映射中key-val键值对的数目;
  • del:通过del hash_map[key] 的语句形式删除key-val关联;
  • in:通过key in hash_map的语句形式,返回key是否存在与关联中,布尔值。

线性探测

开放定址,就是为冲突的数据项再找一个开放的空槽来保存。
向后逐个槽寻找的方法则是开放定址技术中的线性探测。
线性探测法的一个缺点就是聚集的趋势。避免聚集的一种方法就是将线性探测扩展,从逐个探测改为跳跃式探测。

实现Hash_Map

考虑到冲突解决算法,散列表大小应该选择素数。

class Hash_Table(object):
    def __init__(self):
        self.size = 11
        self.slots = [None] * self.size
        self.val = [None] * self.size

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

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

    def add(self, key, val):
        hash_value = self.hash_function(key)
        if self.slots[hash_value] == None:
            self.slots[hash_value] = key
            self.val[hash_value] = val
        else:
            if self.slots[hash_value] == key:
                self.val[hash_value] = val
            else:
                nextslot = self.rehash(hash_value)
                while self.slots[nextslot] != None and self.slots[nextslot] != key:
                    nextslot = self.rehash(nextslot)
                if self.slots[nextslot] == None:
                    self.slots[nextslot] = key
                    self.val[nextslot] = val
                else:
                    self.data[nextslot] = val

    def get(self, key):
        startslot = self.hash_function(key)
        val = None
        stop = False
        found = False
        position = startslot
        while self.slots[position] != None and not found and not stop:
            if self.slots[position] == key:
                found = True
                val = self.val[position]
            else:
                position = self.rehash(position)
                if position == startslot:
                    stop = True
        return val

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

    def __setitem__(self, key, val):
        self.add(key,val)
from ADT_CLASS import Hash_Table

h = Hash_Table()
h[54] = 'cat'
h[26] = 'dog'
h[93] = 'lion'
h[26] = 'pig'
print(h.slots)
print(h.val)
print(h[26])
输出:
[None, None, None, None, 26, 93, None, None, None, None, 54]
[None, None, None, None, 'pig', 'lion', None, None, None, None, 'cat']
pig
  • 3
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

他是只猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值