数据结构与算法【Python实现】(五)哈希表

一、哈希表

哈希表是一个通过哈希函数来计算数据存储位置的数据结构,通常支持如下操作:

insert(key,value):插入键值对(key,value)

get(key):如果存在键为key的键值对则返回其value,否则返回空

delete(key):删除键为key的键值对

直接寻址表:key为k的元素放到k位置上

改进直接寻址表:哈希 Hashing

        构建大小为m的寻址表T

        key为k的元素放到h(k)位置上

        h(k)是个函数,将key的域U映射到表T[0,1,…,m-1]上

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

1、哈希冲突:

由于哈希表大小是有限的,而要存储的值的总数量是无限的,因此对于任何哈希函数,都会出现两个不同元素映射到同一个位置上的情况,这种情况称为哈希冲突

比如h(k)=k%7,h(0)=h(7)=h(14)

2、解决哈希冲突:

(1)开放寻址法:如果哈希函数返回的位置已经有值,则可以向后探查新的位置来存储这个值

        线性探查:如果位置i被占用,则探查i+1,i+2…

        二次探查:如果位置i被占用,则探查i+1^2,i-1^2,i+2^2,i-2^2…

        二度哈希:有n个哈希函数,当使用第一个哈希函数h1发生冲突时,则尝试使用h2、h3…

(2)拉链法:哈希表每个位置都连接一个链表,当冲突发生时,冲突的元素将被加到该位置链表的最后

3、常见的哈希函数:

除法哈希法:h(k)=k%m

乘法哈希法:h(k)=floor(m*(A*key%1))

全域哈希法:h_a,b(k)=((a*key+b) % p) % m    a,b=1,2,…,p-1

拉链法哈希表:

class LinkList:
    class Node:
        def __init__(self,item=None):
            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):
            return self

    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):
        for obj in iterable:
            self.append(obj)

    def find(self,obj):
        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))+">>"


#类似于集合的结构,即元素不允许重复
class HashTable:
    def __init__(self,size=101):
        self.size = size
        self.T = [LinkList() for _ in range(self.size)]  #哈希表T每个位置是一个空链表

    def h(self,k):  #哈希函数h(k)  除法哈希
        return k % self.size

    def insert(self,k):   #插入
        i = self.h(k)
        if self.find(k):  #如果找到了相同元素 则不插入
            print("元素已插入过")
        else:
            self.T[i].append(k)


    def find(self,k):  #查找
        i = self.h(k)     #哈希表中的链表位置
        return self.T[i].find(k)     #在链表中查找


ht = HashTable()
ht.insert(0)
ht.insert(1)
ht.insert(3)
ht.insert(102)
ht.insert(508)

# print(",".join(map(str,ht.T)))
print(ht.find(1))

4、哈希表的应用

(1)字典和集合

字典和集合都是通过哈希表来实现的

        a={‘name’:'anna','age':18,'gender':'female'}

使用哈希表存储字典,通过哈希函数将字典的键映射为下标,假设h('name')=3,h('age')=1,h('gender')=4,则哈希表存储为[None,18,None,'anna','female']

如果发生哈希冲突,则通过拉链法或开发寻址法解决。

(2)MD5算法

MD5曾经是密码学中常用的哈希函数,可以把任意长度的数据映射为128位的哈希值,其曾经包含如下特征:

        同样的消息,其MD5值必定相同

        可以快速计算出任意给定消息的MD5值

        除非暴力的枚举所有可能的消息,否则不可能从哈希值反推出消息本身

        两条消息之间即使只有微笑的差别,其对应的MD5值也应该是完全不同,完全不相关的

        不能能在有意义的时间内人工构造两个不同的消息,使其具有相同的MD5值

如:文件的哈希值

        算出文件的哈希值,若两个文件的哈希值相同,则可认为文件是相同的

用户可以利用它来验证下载的文件是否完整

云存储服务商可以利用它来判断用户要上传的文件是否已经存在于服务器上,从而实现秒传的功能,同时避免存储过多相同的文件副本。

(3)SHA2算法

SHA2具有和MD5类似的性质,安全性较重要的场合推荐使用SHA2等更安全的哈希函数

应用举例:

例如比特币系统,所有参与者需要共同解决如下问题:对于一个给定的字符串U,给定的目标哈希值H,需要计算出一个字符串V,使得U+V的哈希值与H的差小于一个给定值D。此时只能通过暴力枚举V来进行猜测。首先计算出结果的人可获得一定奖金,而某人首先计算成功的概率与其拥有的计算量成正比,所以其获得的奖金的期望值与其拥有的计算量成正比。

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
数据结构与算法Python中可以通过创建新类来实现。例如,栈可以通过创建一个名为Stack的类来实现。栈的操作可以通过方法来实现,比如is_empty()用于判断栈是否为空,push(item)用于将元素压入栈中,pop()用于弹出栈顶元素,peak()用于返回栈顶元素,size()用于返回栈的大小。在Python中,可以使用列表来实现栈的功能。\[1\] 哈希表也可以在Python实现。可以创建一个名为Hash的类,并在该类中定义相关的方法,比如__setitem__函数用于设置哈希表中的键值对。通过创建哈希表的实例对象,并调用相关的方法,可以实现哈希表的操作。例如,可以使用H\[11\] = "tiger"来设置哈希表中键为11的值为"tiger"。\[2\] 此外,Python也提供了各种常用的排序算法实现。例如,冒泡排序可以通过定义一个名为bubble_sort2的函数来实现。该函数可以接受一个列表作为参数,并将列表按照从大到小的顺序进行排序。在排序过程中,可以使用flag来判断列表是否已经有序,如果已经有序,则可以提前结束排序。\[3\] 因此,数据结构与算法可以通过在Python中创建新类或定义函数来实现。这些实现可以利用Python提供的强大的原生集合和方法来完成。 #### 引用[.reference_title] - *1* *2* *3* [数据结构与算法python语言实现,注释详细](https://blog.csdn.net/weixin_45702442/article/details/120026853)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值