链表实现哈希表以及哈希表的应用

'''
哈希表 字典和集合


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

直接寻址表
关键字的全域U比较小时,一种简单而又有效的方法


缺点:
当域U很大,需要消耗大量内存
当域U很大,实际出现的key很少,
无法处理关键字不是数字的情况



直接寻址表:key为k的元素放在k位置上
哈希:
    构建大小为m的寻址表T
    key为k的元素放在h(k)位置上
    h(k)是一个函数,其将域U映射到表T[0,1,...,m-1]

哈希表(散列表):
    是一种线性表的存储结构。哈希表由一个直接寻址表和一个哈希函数组成。哈希函数h(k)将元素关键字k作为自变量,返回元素的存储下标
    假设有一个长度为7的哈希表,哈希函数h(k) = k%7(除法哈希).元素集合{14,22,3,5}的存储方式如图
    14->0位置(14%7 = 0)
    22->1位置(22%7 = 1)
    3->3位置(3%7 = 3)
    5->5位置(5%7 = 5)
  
  
哈希冲突:
    0->0位置
    0位置冲突
    由于哈希表的大小是有限的,而要存储的值的总数量是无限的,因此对于任何哈希函数,都会出现两个不同的元素映射到同一个位置上的情况,这种情况叫做哈希冲突
        
解决方法:
开放寻址法:  
        如果哈希函数返回的位置已经有值,则可以向后探查新的位置来存储这个值
    线性探查:
        如果位置i被占用,则探查i+1,i+2,....直至找到一个位置
    二次探查:
        如果位置i被占用,则探查i+1**2,i-1**2,i+2**2,i-2**2,.....
    二度哈希:
        有n个哈希函数,当使用第一个哈希函数h1发生冲突时,则尝试使用h2,h3,......

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


常见的哈希函数:
        除法哈希:
        h(k) = k % m
        
        
        乘法哈希:
        h(k) = floor(m*(A*key%1))
            A 是一个任意值,
            m是大小,
            floor 是向下取整
            
            
        全域哈希法:
        h(a,b)(k) = ((a*key + b) mod p )mod m     a,b  = 1,2,...,p-1
            mod 就是 % 取模 
            (a,b)是下标
            
        
'''


# 哈希表的实现


# 定义一个链表类
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)) + ">>"


# lk = LinkList([1,2,3,4,5])
# for element in lk:
#     print(element)


# 类似于集合的结构
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 find(self, k):
        i = self.h(k)
        return self.T[i].find(k)

    def insert(self, k):
        i = self.h(k)
        if self.find(k):
            print("重复插入!!")
        else:
            self.T[i].append(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(22))

# 哈希表的应用
# 字典与字典

# MD5算法
# 文件拥有哈希值
# SHA2算法
# 比特币系统

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值