15、python数据结构——哈希表

哈希表是一个哈希函数来计算数据储存位置的数据结构,通常支持如下操作:
insert(key,value):插入健值对(key,value)
get(key):如果存在键key的健值则返回value,否则返回空值
delete(key):删除键为key的健值对

直接寻址表

直接寻址表可以理解为普通的字典,就是在整个域(内存)中去寻找健值(key)的位置,找到健值后,再通过健值去找到对应的内容。当关键字的全域比较小的时候,直接寻址是一种简单有效的方法。
但是当全域很打的时候,需要消耗大量的内存;且如果全域很大,但是实际出现的key很少,则会浪费大量空间;并且无法处理关键字不是数字的情况。

哈希(Hashing)

直接寻址表:将key=k的元素放在k上;
改进方法:哈希
1、构建好大小为m的寻址表
2、key=k的元素放在h(k)位置
3、h(k)是一个函数,主要是起到映射的作用

哈希表(散列表)是一种线性表的储存结构,是由 直接寻址表+哈希函数 组成,哈希函数h(k)将元素关键字k作为自变量,返回元素的存储下标。

哈希冲突是由于哈希表的大小是有限的,而存储的值的总数量是无限的,因此会出现两个不同元素映射到同一个位置上的情况,这种情况就叫做哈喜冲突。例如:h(k)=k%4,h(0)=h(4)=h(8)=……

解决哈希冲突的方法有很多种:开放寻址法;线性探查;二次探查;二度哈希;拉链法……
这里我们详细说明拉链法。拉链法是哈希表每个位置都连接一个链表,当冲突发生时,冲突的元素将被加到该位置链表的最后。

常见的哈希函数有:除法哈希法:h(k) = k % m;乘法哈希法:h(k) = floor(m*(Akey%1));全域哈希法:h-a,b-(k)=((akey+b) mod p) mod m a,b=1,2…,…p-1

我们需要先建立一个满足哈希表需求的链表,即将列表给转化为链表。
代码如下:

class LinkList():
    class Node():           # 普通链表节点
        def __init__(self,item):
            self.item = item
            self.next = None

    class LinkListIterator():    # 创建链表迭代器
        def __init__(self,node):
            self.node = node
        def __next__(self):
            if self.node:
                cur_node = self.node
                self.node = cur_node.next
                return cur_node.item    # 返回得到另外一个节点
            else:
                raise StopIteration
        def __iter__(self):    # 这个必须要写,不写的话,显示LinkListIterator实例是不可迭代的   不懂看这个网站https://zhuanlan.zhihu.com/p/354115606
            return self        # return self 的作用是实例化对象  不懂可以看这个网站:https://blog.csdn.net/weixin_44799217/article/details/126131716
    def __init__(self,iterable=None):     # 没有输入的时候,就不需要扩展链表
        self.head = None
        self.tail = None
        if iterable:
            self.extend(iterable)
    def append(self,obj):       # 把列表元素转化为链表节点元素
        s = LinkList.Node(obj)
        if not self.head:
            self.head = s
            self.tail = s
        else:
            self.tail.next = s
            self.tail = s
    def extend(self,iterable):    # 将列表元素一个一个给使用append函数转化为链表节点
        for obj in iterable:
            self.append(obj)
    def find(self,obj):   # 这里的self表示的是单个链表的所有内容
        print(self)
        for n in self:
            if n == obj:
                return True
        else:
            return False
    def __iter__(self):
        return self.LinkListIterator(self.head)    # 允许链表迭代器从头节点开始迭代
    def __repr__(self):
        return "<<"+",".join(map(str,self)) + ">>"    # 直接输出实例对象,而不是一个地址   不懂就看https://zhuanlan.zhihu.com/p/393657724
# 测试主函数
lk = LinkList([1,2,3,4,5])
print(lk)
# 建立哈希表的类(再上面链表的基础上)
# 类似于集合的结构
class HashTable():
    def __init__(self,size=100):
        self.size = size
        self.T = [LinkList() for i in range(self.size)]    # 创建一个列表,列表里面每一个元素都是链表
    def h(self,k):                    # 建立返回余数的函数
        return k % self.size
    def insert(self,k):
        i = self.h(k)
        if self.find(k):        # 起到去重的作用,已经存在的话就不再存进去了
            print("Duplicated Insert.")
        else:
            self.T[i].append(k)
    def find(self,k):           # 返回链表设置的另外一个find函数,如果这个输入值在我们的链表里面了,就不用再插入了
        i = self.h(k)
        return self.T[i].find(k)    # 在第i个位置去找里面是否有重复的数字
# 哈希表主函数
ht = HashTable()
ht.insert(0)
ht.insert(1)
ht.insert(0)
ht.insert(2)
ht.insert(101)
print(",".join(map(str,ht.T)))
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值