首页 > 其他分享 >哈希表

哈希表

时间:2023-01-10 19:44:28浏览次数:33  
标签:__ node 函数 self 哈希 def

1. 哈希表的概念

  哈希表:也叫做散列表。根据关键字和值(Key-Value)直接进行访问的数据结构。它通过关键字 key 和一个映射函数 Hash(key) 计算出对应的值 value,然后把键值对映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做哈希函数(散列函数),用于存放记录的数组叫做 哈希表(散列表)。

 

2. 哈希函数

  将哈希表中元素的关键键值映射为元素存储位置的函数。如h(k) = k % 10,设置10个长度空间,模相同的放在同一个下标空间

  哈希函数的特征:

   1. 哈希函数应该易于计算,并且尽量使计算出来的索引值均匀分布,这能减少哈希冲突  

   2. 哈希函数计算得到的哈希值是一个固定长度的输出值

   3. 如果Hash(key1) 不等于 Hash(key2),那么 key1、key2 一定不相等

   4. 如果 Hash(key1) 等于 Hash(key2),那么 key1、key2 可能相等,也可能不相等(会发生哈希碰撞)

 

3. 哈希冲突

  1. 概念:不同的关键字通过同一个哈希函数可能得到同一哈希地址,即 key1 ≠ key2,而 Hash(key1) = Hash(key2),这种现象称为哈希冲突。

  2. 解决哈希冲突的方法

   1. 开发地址法:如果哈希函数返回的地方有值,则向后寻找新的空位置来存储该值

     1. 线性探查法:如果H(i) 被占用,则探查i+1,i+2.....

     2. 二次探查法:如果H(i) 被占用,则探查i+1²,i-1²,i+2²,i-2²......

     3. 二度哈希法:使用N个哈希函数,当使用第一个哈希函数发生冲突时,尝试使用其他的H2,H3等哈希函数

   2. 拉链法:将具有相同哈希地址的元素(或记录)存储在同一个线性链表中。

    

 

4. 实现哈希表的拉链插入法

# 链表
class LinkList:
    # 构建节点类
    class Node:
        def __init__(self, item=None):
            self.item = item
            self.next = None
    # 构建迭代器,因为容器类对象不可迭代
    class LinkListIterator:
        def __init__(self, node):
            self.node = node
        # 迭代器__iter__
        def __iter__(self):
            return self
        # 迭代器__next__
        def __next__(self):
            if self.node is not None:
                cur_node = self.node
                self.node = cur_node.next
                return cur_node.item
            else:
                raise StopIteration

    # 对象实例化
    def __init__(self, iterator=None):
        self.head = None
        self.tail = None
        # 判断调用类的时候如果参数是一个可迭代对象,则循环插入链表
        if iterator:
            self.extend(iterator)
    # 插入元素
    def append(self, val):
        node = LinkList.Node(val)
        # 判断链表是否为空,为空则head和tail都指向插入元素
        if not self.head:
            self.head = node
            self.tail = node
        # 不为空,则指针的next指向插入元素,并且更新指针尾插入元素
        else:
            self.tail.next = node
            self.tail = node
    # 插入可迭代列表函数 我自己不会想到这个,默认调用的时候不传参数
    def extend(self, iterator):
        for i in iterator:
            self.append(i)
    # 查找元素
    def find_LinkList(self, val):
        for n in self:
            if n == val:
                return True
            else:
                return False
    # 链对象可迭代化
    def __iter__(self, iterator=None):
        return self.LinkListIterator(self.head)
    # 输出字符串化,内置函数
    def __repr__(self):
        return "<"+",".join(map(str, self))+">"

# 类似于集合的结构
class HashTable:
    def __init__(self, size=100):
        self.size = size
        self.table = [LinkList() for i in range(self.size)]     # 建立空链表
    # 哈希函数,确定存储下标位置
    def hash_function(self, k):
        return k % self.size
    # 查找元素
    def find_HashTable(self, val):
        i = self.hash_function(val)         # i为哈希函数返回值,即指向哪一个链表
        return self.table[i].find_LinkList(val)      # 在指定i的链表中调用find_LinkList函数查找插入元素是否存在该链表中
    # 插入元素
    def insert(self, val):
        i = self.hash_function(val)     # 获取插入链表位置下标i
        if self.find_HashTable(val):    # 查找插入元素是否存在
            print("重复插入!")
        else:
            self.table[i].append(val)   # 不存在则调用append函数

 

5. 扩展小知识

  python中的集合和字典本质上就是哈希表,集合要求元素不能重复,字典要求键唯一不可变,是可以通过哈希函数计算出唯一地址的,键可以是数字、字符串和元组,但是元素内的元素要规定不能是列表,字典,集合等可变的对象。字典通过将键作为参数进行转换,得到唯一的地址,然后将值存放在该地址中,这是为什么当键相同的时候,值会被覆盖掉的原因

  Python 的哈希算法对相同的值计算得到的结果是一样的,也就是说 314 和 314.0 的值相同,他们被认为是相同的键(Key)

标签:__,node,函数,self,哈希,def
From: https://www.cnblogs.com/chf333/p/17036858.html

相关文章

  • Python获取URL图片文件的哈希值 hash
    pipinstallPillow importhashlibfromioimportBytesIOdefget_hash(file):""":parambytesfile::return:"""md5hash=hashlib.m......
  • 哈希
    packagecom.EqualsExercise01;publicclassTest{/*1.提高具有哈希结构的容器的效率2.两个引用或者多个引用,如果指向的是同一个对象,则哈希值肯定一样......
  • AtCoder Beginner Contest 284-F - ABCBAC(双哈希)
    F-ABCBAC题目大意:给定一个正整数n,和一个长度为2*n的字符串s问s串能不能是由一个t串经过如下操作变成s串:t串的前i个字符t串的反转串t串的后(n-i)个字符如果存在......
  • 【哈希表】LeetCode 299. 猜数字游戏
    题目链接299.猜数字游戏思路建立两个哈希表分别存储secret和guess中不是bulls的数字出现次数。代码classSolution{publicStringgetHint(Stringsecret,......
  • 【哈希表】LeetCode 350. 两个数组的交集 II
    题目链接350.两个数组的交集II思路建立两个哈希表分别统计nums1和nums2中每个数字出现的个数,然后同时遍历两个哈希表,对两个对位元素取其最小值count,将count数......
  • 【哈希表】LeetCode 49. 字母异位词分组
    题目链接49.字母异位词分组思路如果一对字符串是字母异位词,那么他们经过排序之后,应该是相等的。利用这一特点,我们通过哈希表建立排序后字符串到原字符串列表的映射,不......
  • 【删除交换】【哈希表】LeetCode 380. O(1) 时间插入、删除和获取随机元素
    题目链接380.O(1)时间插入、删除和获取随机元素思路下面引用宫水三叶大佬的题解insert操作:使用哈希表判断val是否存在,存在的话返回false,否则将其添加到nums,更......
  • 内网渗透-PTH&PTK&PTT哈希票据传递
    1.PTH(passthehash) 1)利用lm或ntlm的值进行的渗透测试2)PTH在内网渗透中是一种很经典的攻击方式,原理就是攻击者可以直接通过LMHash和NTLMHash访问远程......
  • 【哈希表】LeetCode 1. 两数之和
    题目链接1.两数之和思路使用HashMap来存储每个元素的下标及其所需要加和的数,遍历数组,检查每个数是否在HashMap中有对应的加和数,如果没有则把该数也加入HashMap中......
  • C# 哈希表(Hashtable)
    原文链接:http://edu.jb51.net/csharp/csharp-collection-hashtable.htmlHashtable类代表了一系列基于键的哈希代码组织起来的键/值对。它使用键来访问集合中的元素。当......