Python字典hash表的模拟实现

哈希算法核心原理与Python实践:从数据指纹到安全应用 哈希算法是计算机科学中的基础技术,它将任意长度的数据映射为固定长度的唯一摘要,常被称为数据的“指纹”。其核心原理基于确定性、高效性、抗碰撞性和雪崩效应四大特性,确保相同输入永远产生相同输出,且微小改动会导致结果剧变。这一原理在工程实践中价值巨大,支撑着数据结构的高效实现,例如哈希表(Hash Table)通过O(1)时间复杂度实现快速查找。在安全领域,哈希算法是数据完整性校验和密码存储的基石,通过加盐(Salt)和慢哈希技术,有效防御彩虹表等攻击。本文以Python的hashlib模块为例,深入解析如何正确 阅读详情

本文学习自:《Python 源码深度剖析》

  • 感谢作者的传授
  • 若还不清楚字典的知识, 详细内容和知识点可点击了解

功能

主类(字典):PyDictObject

  • (1) add_entry(self, key, value) : 添加元素
  • (2)del_entry(self, key) : 删除元素
  • (3) get_entry(self, key): 查找键对应的值(与删除采用相同的函数,通过flag 标志区分)
  • (4) hash_list : (属性),可以遍历底层hash数组
  • (5) entry_list: (属性),遍历底层键值对数组
  • (6) 可通过简单的 for循环迭代,很方便
pd = PyDictObject()
''' 查看原始hash表存储情况 '''
# for 循环遍历
for i in pd.ma_keys:
    print(i)

# 或者 生成器表达式, 再转化为字典
a = (i for i in pd.hash_list)
print(list(a))

# 查看底层键值对数组情况
b = (i for i in pd.entry_list)
print(list(b))
内部功能:
  • 扩容, 伪扩容,缩容的实现。 hash冲突的预防,探测(线性探测,平方探测)
  • 其中探测分为 两种方式(线性探测和平方探测依次循环探测)
  • 修改或者是增加使用相同的函数(底层自动监测是否有相同的key,决定是否 更新数据 或者新增数据)

PyDictKeysObject

  • 完成主要的所有核心的功能

De_Entries

  • 键值对数组

Dk_Indices

  • 散列表

Entry

  • 散列表数组元素
  • 包含状态 和 键值对存储下标 两个属性

PyDictKeyEntry

  • 键值对对象
  • 定义了几个方法,操作键值对

主要的功能示意图:

扩容缩容(可能与源码的实现有些不同)

在这里插入图片描述

删除逻辑(字体较为潦草~)

  • 因为总是先进行比较,若不相同才会有 探测这一步,所以总觉得是 do while循环,先执行一次,再做做判断循环,但是 python中没有do while循环, 所有就是用了 while True: pass (具体参考删除逻辑的代码)
    在这里插入图片描述

测试

  • 循环10000次,除性能问题外,基本可以排除所有bug,不会因代码本身逻辑问题,导致代码异常出 bug,健壮性还可以。
  • 每次哈希探测的次数,均少于10次(异常退出设置的是十次,可能探测次数更低)

问题

  • (1) 首先并没有复刻一个对象的 头部,也就是没有考虑到删除或者修改一个对象时,内存管理,垃圾回收的问题。 因为没有设置 refcnt字段去 考虑垃圾回收。
  • (2)字典当中,有些字段并没有使用上,也就荒废了。
  • (3) 很多功能感觉很简单~,但是测试时会有很多逻辑上的漏洞和bug, 代码不断更新,完善。 即使是一个很小的东西,要想万无一失,都需要钻牛角尖,仔细考虑完善,很佩服 语言的开发者,实现整个语言的功能,还要避免漏洞。
  • (4) 本来想复刻一下,字典的遍历, for i in range dict.items等 按照键,按照值 等方式遍历, 但是 底层都是去 遍历 键值对数组, 但键值对数组的迭代器,是共用一个 i变量遍历的, 这就涉及到,当同时去 遍历键, 值等的时候, i值的问题所以就没实现

感悟:

起初设计的时候,感觉要写个很多代码,能实现一个大的功能,结果实现的时候,仅仅用了300行代码~ 另外很多东西只有实践的时候,才能去真正了解他的细节, 包括一个字段, 一段处理逻辑, 一丁点地方都需要去反复求证,才能下手。 另外对 程序的设计 还有思路方面有很大的收获, 诚然现在的代码,质量还不高,很多重要的地方,因为思维局限,写代码时还未考虑,但进步还是有的。

代码展示

class Me_Key():
    """ 定义数据描述器,限定 Me_key 值为可hash的 """

    def __init__(self, name):
        self.attrname = name

    def __get__(self, instance, owner):
        return getattr(instance, self.attrname)

    def __set__(self, instance, value):
        # 当数据是 字典或者列表,我们就认为是不可哈希的,返回错误
        if isinstance(value, dict) or isinstance(value, list):
            raise("键错误,不可哈希")
        setattr(instance, self.attrname, value)


class PyDictKeyEntry():
    """ 定义存储的键值对 对象,PyDictKeyEntry """

    me_key = Me_Key('_key')
    def __init__(self):
        """
        :param    me_hash: 键对象的 哈希值 ,避免重复调用 __hash__ 计算哈希值;
        :param    me_key: 键对象指针;
        :param    me_value: 值对象指针;
        """
        self.me_key = None 
        self.me_value = None
        self.me_hash = None
    
    def set_data(self, key, value):
        
        self.me_key = key
        self.me_value = value
        self.me_hash = hash(key)

    def del_data(self):   # 默认全部设置为None, 就是删除了
        self.me_key = None
        self.me_hash = None
        self.me_value = None
    

class Entry():
    """ 定义散列表每一个格子 """

    # 定义三种状态
    EMPTY = 1
    DUMMY = 2
    USED = 3

    def __init__(self):
        self.status = self.EMPTY
        self.index = None

class Dk_Indices():
    """ 定义dk_indices 散列表 """
    entry = Entry

    def __init__(self, n = 8):
        """
            散列表定义初始长度为8
        """
        self.hash_table = [self.entry() for i in range(n)]


class De_Entries():
    """ 定义存储键值对数组 """
    pke = PyDictKeyEntry

    def __init__(self, n = 5):
        self.i = -1
        self.length = n
        self.entries = [self.pke() for i in range(n)]
    
    def __iter__(self):
        self.i = -1
        return self
        
    def __next__(self):

        while self.i < self.length -1:
            self.i += 1
            return self.entries[self.i].me_key, self.entries[self.i].me_value
        raise StopIteration


class PyDictKeysObject():
    """ 定义哈希表对象结构 """

    indices = Dk_Indices
    entries = De_Entries
    def __init__(self):
        """
            :param    dk_size: 哈希表大小
            :param    dk_usable: 键值对数组可用个数
            :param    dk_nentries: 键值对已用个数 (因为删除数据了, 可用加上已用,并不等于键值对数组大小,还有的删除状态不再使用了),当数据删除时,已用个数减一,但是可用个数不变
            :param    dk_indices: 存储dk_entries数组对应元素下标(也是hash表)
            :param    dk_entries: 保存键值对的数组
            :param    de_deldatas: 删除元素的个数
        """
        # 初始化数据,散列表总长度8,键值对数组长度5(三分之二长),已用个数为0
        self.dk_size = 8
        self.dk_usable = 5
        self.dk_nentries = 0
        self.de_deldatas = 0
        self.dk_indices = self.indices()
        self.dk_entries = self.entries()

        # 用于迭代器计数
        self.i = -1
    
    def find_location(self, me_key, me_value):
        """ 寻找数据的 hash表存储位置,并插入 """
        ''' 官网的根据 对象hash值选择,生成不同的探测序列,我们搞简单的,利用线性和平方探测,交替进行,减少冲突 '''

        # 这里用一个技巧,取模运算,被代替为 按位与& 运算, 因为hash表的长度为dk_size =  2的n次方, 则2的n次方减一,二进制恰好是 低位全1,高位为0,相与即是等于 与 dk_size 取模运算,但更速度!https://blog.youkuaiyun.com/u014266077/article/details/80672995
        a = self.add_entries_data(me_key, me_value)
        if not a: 
            return
        self.insert_hash_index(a)
        # 数据插入成功,更新 self.dk_usable     self.dk_nentries 字段的值
        self.dk_usable -= 1
        self.dk_nentries += 1
        print("+++++", self.dk_usable)
    
    def insert_hash_index(self, a):
        location = a.me_hash & (self.dk_size - 1)
        entry = self.dk_indices.hash_table[location]
        s = self.status_1_2(entry)

        if not s:
            sequence = entry.status
            n = 1
            while sequence == 3:
                # 防止冲突算法不好,程序陷入死循环,最多查找十次
                n += 1
                if n > 10:
                    print("这~~ 执行十次都找不到插入的位置。。")
                    raise TimeoutError
                location = self.linear_detect(location)  # 线性探测
                temp =  self.dk_indices.hash_table[location]  
                sequence = temp.status
                if sequence == 3:
                    location = self.square_detect(location)  # 平方探测
                    temp =  self.dk_indices.hash_table[location]
                    sequence = temp.status
            self.status_1_2(temp)
    
    def del_element(self, key, flag = 1):
        """ 定义删除元素的函数 """

        try:
            hash_key = hash(key)
        except TypeError as e:
            print("提示:传入的键是不合法的,请重新尝试!")
            raise(e)
        location = hash_key & (self.dk_size - 1)
        entry = self.dk_indices.hash_table[location]
        n = 0
        while True:
            if n != 0:
                if n & 1 == 1:
                    location = self.linear_detect(location)  # 线性探测
                else:
                    location = self.square_detect(location)  # 平方探测
                entry = self.dk_indices.hash_table[location]

            if entry.status == 1:
                raise KeyError
            elif entry.status == 2:
                n += 1
                continue
            else:
                array_key_value = self.dk_entries.entries[entry.index]
                if hash_key == array_key_value.me_hash:
                    if flag == 2:
                        print("执行get()")
                        return array_key_value.me_value
                    print("执行删除")
                    self.de_deldatas += 1
                    entry.status = 2
                    entry.index = None
                    array_key_value.del_data()
                    break
                else:
                    n += 1
    

    def add_entries_data(self, key, value):
        """ 向键值对数组插入数据 """

        temp = self.dk_entries.pke()
        temp.set_data(key, value)
        for i in self.dk_entries.entries:
            if i.me_hash == temp.me_hash:
                print("执行修改操作")
                i.me_value = temp.me_value
                break
        else:
            # 判断是否需要扩容
            if not self.cheack():
                # 执行扩容
                self.expansion()
            a = self.dk_entries.entries[self.dk_nentries]
            a.set_data(key, value)
            return a
    
    def cheack(self):
        """ 插入数据时对 键值对数组进行检查,是否会出现元素溢出,进行相应的扩容,或者缩容操作 """
        return False if self.dk_usable == 0 else True

    def expansion(self):
        """ 扩容函数 """

        # used, 除去删除的,真正已用的, entries就是键值对数组的长度
        used = self.dk_nentries - self.de_deldatas 
        entries = (self.dk_size*2 // 3)
        if used > entries*3 // 4 :
            print("执行双扩容")
            # 重新初始化数据
            self.dk_size *= 2
            self.dk_indices = self.indices(self.dk_size)  # 和下面的初始化操作一样,可以 重写一个方法,但是程序执行速度太低了
            self.dk_usable = self.dk_size*2 // 3
            self.dk_nentries = 0
            # 分配键值对数组,与重新插入 hash表
            self.redistribute()
        elif used >= entries // 2 :
            print("执行伪扩容")
            self.dk_indices = self.indices(self.dk_size)
            self.dk_usable = self.dk_size*2 // 3
            self.dk_nentries = 0
            self.redistribute()
        else:
            print("执行缩容")
            # 默认最小长度是8,不允许缩容
            if self.dk_size == 8:
                return 
            n = 1
            i = 0
            while n < used * 3:  # 计算最小的满足 键值对为hash大小1/3, 的n (n表示2的n次方)
                n *= 2
                i += 1
            # 初始化数据
            self.dk_size = 2 ** i
            self.dk_indices = self.indices(self.dk_size)
            self.dk_usable = self.dk_size*2 // 3
            self.dk_nentries = 0
            self.redistribute()

    def redistribute(self):
        """ 重新分配 hash,键值对数组 """

        i = 0
        temp = self.entries(self.dk_size*2 // 3)
        for data in self.dk_entries.entries:
            if data.me_hash == None:
                continue
            temp.entries[i] = data
            self.insert_hash_index(data)
            self.dk_usable -= 1
            self.dk_nentries += 1
            i += 1
        self.dk_entries = temp

    def status_1_2(self, b):
        """ 转态转换: EMPTY 与 DUMMY """
        ''' 用来判断状态 1,2 说明不存在hash冲突,返回True,否则返回False '''
        if b.status != 3:
            b.index = self.dk_nentries
            b.status = 3    
            return True
        else:
            return False    

    def linear_detect(self, index):
        """解决hash冲突,开放地址法,线性探测方法"""
        # 经过试验,当后面 +3时, 循环一万次添加数据时,都不会出现死循环, 为0或 1都不行, 看来解决冲突的算法真的很重要
        return (index * 2 + 3) & (self.dk_size - 1)

    def square_detect(self, index):
        """ 平方探测 """
        return (index ** 2) & (self.dk_size - 1)

    # 定义成迭代器,方便查看 散列表内的元素存储情况
    def __iter__(self):
        self.i = -1  # 当多次for 循环时, i值必须重新初始化,从头开始
        return self
    
    def __next__(self):
        while self.i < self.dk_size: 
            self.i += 1
            if self.i == self.dk_size:
                break
            return self.dk_indices.hash_table[self.i].index, self.dk_indices.hash_table[self.i].status
        raise StopIteration


class PyDictObject():

    pdk = PyDictKeysObject
    
    def __init__(self):
        """初始化大整数
        :param    ma_used: 对象当前所保存的键值对个数
        :param    ma_version_tag:对象当前版本号,每次修改时更新
        :param    ma_keys:指向映射的hash表结构
        :param    ma_values: 分离模式下指向由所有 值对象 组成的数组
        """
        
        # 定长对象 公共头字段:PyObject_HEAD, 里面ob_refcnt, 
        self.ma_used = 0
        self.ma_version_tag = 1
        self.ma_keys = self.pdk()
        self.ma_values = None
    
    @property  # hash数组
    def hash_list(self):
        return self.ma_keys
    
    @property  # 键值对数组
    def entry_list(self):
        return self.ma_keys.dk_entries

    # 添加 键值对数据
    def add_entry(self, key, value):
        self.hash_list.find_location(key, value)

    # 查询一个 键对应的值
    def get_entry(self, key):
        return self.hash_list.del_element(key, flag = 2)

    # 删除键值对数组
    def del_entry(self, key):
        self.hash_list.del_element(key)

    def __iter__(self):
        return self

    # Entry数组的"不可变性", Python3.7中,支持按插入顺序迭代
    def __next__(self):
        pass



pd = PyDictObject()
# pd.add_entry(123, 789)

for i in range(0, 42):
    pd.add_entry(i, i)


for i in range(37):
    pd.del_entry(i)
pd.add_entry(48, 34)

pd.add_entry(39, "hash")

print(pd.get_entry(37))
''' 查看原始hash表存储情况 '''
# for 循环遍历
# for i in pd.ma_keys:
#     print(i)

# 或者 生成器表达式, 再转化为字典
a = (i for i in pd.hash_list)
print(list(a))

b = (i for i in pd.entry_list)
print(list(b))


 
Python中的哈希算法与Trie树详解 本文详细介绍了哈希算法和Trie树的基本概念、实现方法及其在实际应用中的作用。通过面向对象的方式实现了哈希表和Trie树的基本操作,并结合具体案例展示了它们的应用场景。哈希算法适合快速查找和插入的需求,而Trie树则在处理字符串时表现出色。理解这两种数据结构及其特点,将有助于在实际开发中选择合适的工具和方法。希望本文能为读者提供关于哈希算法与Trie树的深入理解和应用指导。如果有进一步的问题或需求,欢迎随时讨论! 阅读详情

相关推荐

Python字典与MATLAB字典模拟技巧:从基础到进阶

Python字典是该语言中一种非常灵活且强大的数据结构。它允许我们存储键值对(key-value pairs),其中的键必须是唯一的,并且不能是可变的数据类型,例如列表。值则可以是任意的数据类型,包括其他字典,这使得字典结构可以很容易地实现嵌套。Python字典是无序的,直到Python 3.7,而从Python 3.7开始,字典保持了插入顺序,这在实际编程中非常重要,因为它可以让我们更直观地理解和操作数据。在Python中创建字典非常简单,可以通过花括号{}直接创建,也可以使用dict()

weixin_35886636的博客 1161

python,使用字典(哈希表)记录数组中每个数字以及对应出现的次数

python

qq_44703354的博客 1100

MedicalNet实战:3D医疗影像分割从零到部署(PyTorch+ResNet50)

本文详细介绍了基于PyTorch和MedicalNet预训练模型进行3D医疗影像分割的完整实战流程。通过加载ResNet50预训练权重进行迁移学习,大幅降低了对标注数据量的需求,并提升了模型性能。文章涵盖了从数据准备、模型微调、训练优化到最终部署的每一步,为医疗AI开发者提供了从零到部署的清晰指南。

weixin_29062671的博客 587

Python 容器(List、Set、Hash、Dict)

Python 容器(List、Set、Hash、Dict)容器1、列表(1)列表的定义(2)元素的访问(3)遍历列表(4)列表的常见方法2、元组3、集合(1)集合的创建(2)集合的常见方法4、字典(1)字典的创建(2)元素的访问(3)常见方法 容器 列表(list) 元组(tuple) 集合(set) 字典(dict) 1、列表 线性表: 数组:连续内存的实现 栈:先进后出,后进先出 队列:先进先出,后进后出 链表: 单向链表:为指针指向首地址 双向链表:收尾指向 Python

XY0918ZWQ的博客 889

手把手教你给H3C MSR路由器配置4G/5G上网(保姆级图文教程)

本文提供H3C MSR路由器配置4G/5G上网的保姆级图文教程,涵盖硬件准备、运营商适配、命令行配置、多运营商策略优化及信号故障排查等全流程。通过实测数据和典型场景分析,帮助用户快速实现4G/5G模块的部署与优化,提升网络稳定性和业务连续性。

weixin_28745067的博客 435

一维光子晶体态密度计算与应用解析

态密度(DOS)是凝聚态物理和光子学中的核心概念,描述了量子态在能量空间的分布规律。基于麦克斯韦方程组的周期性介电结构分析表明,一维光子晶体通过布拉格散射形成光子带隙,其态密度曲线呈现典型的范霍夫奇点和禁带特征。这种特性使光子晶体在光学工程中具有重要价值,特别是在滤波器设计和传感器开发领域。通过转移矩阵法等数值计算手段,可以精确预测带隙位置和宽度,其中折射率对比度与周期数是关键设计参数。实际应用中,1550nm通信波段滤波器常采用Si/SiO2交替结构,而引入缺陷层则能产生高Q值缺陷模。计算优化时需注意数值

weixin_36487018的博客 193

【python资料】字典的hash散列结构

实际上python的字典有非常优秀的数据索引能力;虽然他看上去比Array更复杂笨重,比如key是一个字符串,但是,通过hash映射后,该Key值能直接映射到地址,达到O(1)的时间复杂性。本文讲述他们的原理。

gongdiwudu的专栏 5371

山景BP10_128DBG开发板通过蓝牙连接手机放歌实验回顾

最近在学习上海山景公司的BP10_128DBG的开发板,因为网上关于BP10开发板的帖子也比较少,在学习的时候也没有太多的参考资料,基本上都是官方的历程。蓝牙放歌这个demo对我来说也比较复杂,特写下此博客进行记录、总结,大家有需要的可以参考。

weixin_56646002的博客 2019

【Python 数据结构 15.哈希表】

哈希表的每个数据,保留了链表头结点和尾结点,插入前需要先进行查找,如果找到的位置链表非空,则插入尾结点,并且更新尾结点。哈希表的每个数据就是一个键,插入之前需要先进行查找,如果找到的位置未被插入则执行插入,否则找到下一个未被插入的位置进行插入。如果键存在于字典中,则返回对应的值;,无论是开放地址法,还是链地址法,都可以实现哈希表,我们只需要选择其中一种即可。计算它的哈希值,对数组长度 n 取模以后,找到合适的位置,遍历这个位置上的链表,,只要哈希表足够大,总能找到一空的位置,并且记录下来作为它的哈希值,

m0_73983707的博客 3211

Agentic AI商业化落地指南:提示工程架构师的7步优化法

Agentic AI(具备自主感知、决策与行动能力的智能体系统)是未来AI商业化的核心方向,其价值在于将大模型的“认知能力”转化为“实际行动”,解决复杂商业场景中的自动化与个性化需求。而提示工程(Prompt Engineering)作为连接人类意图与智能体行为的“翻译器”,直接决定了智能体的可控性、效率与用户体验,是Agentic AI商业化落地的关键支撑。本文结合第一性原理与工程实践,提出提示工程架构师的“7步优化法”,覆盖从“商业目标定义”到“规模化推广”的全流程。通过理论框架推导架构设计拆解。

AI架构全栈开发实战笔记 1万+

玩转大语言模型——使用华为官方MindIE-Server镜像方式部署DeepSeek模型

本文将详细介绍在国产Linux系统欧拉中使用华为官方MindIE-Server镜像方式部署DeepSeek模型。一般情况下华为昇腾800I服务器可以推理DeepSeek-R1-70B,4张300I-Duo服务器可以推理DeepSeek-R1-32B。在配置中尽量贴合官方文档,包含用到的一些其他的技术细节,便于零基础入门使用。

艾醒的博客 1288

Python 哈希表的实现——字典

接触过 Python 的小伙伴应该对【字典】这一数据类型都了解吧虽然 Python 没有显式名称为“哈希表”的内置数据结构,但是字典是哈希表实现的数据结构在 Python 中,字典的键(key)被哈希,哈希值决定了键对应的值(value)在字典底层数据存储中的位置那么今天我们就来看看哈希表的原理以及如何实现一个简易版的 Python 哈希表ps:文中提到的 Python 指的是 CPyhton 实现。

aobulaien001的博客 1330

Transformer实战——Transformer自编码模型

自编码模型依赖于原始 Transformer 编码器,并且在解决分类问题时非常高效。除了 BERT 外,还有许多流行的自编码模型,在本节中,我们将一些除 BERT 外的自编码模型,这些模型的目标是通过优化预训练过程、增加层数或头数、改善数据质量、设计更好的目标函数等,来在下游任务上取得更好的表现。这些改进大致可以分为两个方面,更好的架构设计选择和预训练控制。

盼小辉丶的博客 9292

05 - Python入门 - 常用数据结构

上一篇我们学了函数、、列表推导式等语法糖。这篇是整个 Python 教程中最重要的一篇——我们要系统学习 Python 中刷算法题最常用的数据结构。算法题的本质就是对数据结构进行操作,如果你不熟悉这些数据结构的基本用法,看算法代码就会一头雾水。好消息是,Python 的数据结构用起来非常简洁直观,你不需要记住所有 API,只需要掌握最常用的那几个操作就够了。用多了自然就记住了,忘了随时可以回来查。列表是 Python 中最基础、最常用的数据结构,你可以把它理解为"可变长度的数组"。几乎所有算法题都离不开它。

2504_91116606的博客 517

LAMMPS-使用MATLAB计算径向分布函数

首先需要使用LAMMPS进行分子动力学模拟,并获取到所需的数据文件,LAMMPS是一款开源的分子动力学模拟软件,可以模拟原子、分子和离子的运动行为,对于本文的目标假设你已经完成了LAMMPS的安装和模拟过程,获得了数据文件。)是一种重要的统计工具,用于描述原子或分子之间的空间分布情况,通过计算RDF可以获得物质的结构信息、相互作用距离以及相位转变等重要参数,本文将介绍如何使用MATLAB计算LAMMPS生成的数据文件的径向分布函数。变量替换为你的实际数据文件的名称。

weixin_50547796的博客 514

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

python小胶囊 - 集合与字典的存储方式

本文探讨了Python中哈希表的原理与应用。首先通过TypeError问题引出哈希概念,解释哈希表通过散列函数实现快速查找的特性。分析可变对象不可哈希的原因,并介绍hash()和hashlib模块创建哈希对象的方法。重点讲解集合和字典的哈希存储机制,包括负载因子和哈希冲突的开放寻址法、链表法两种解决方案。最后指出Python 3.6+字典已保留插入顺序的特性,并对比了OrderedDict的实现。文章通过实例演示了哈希表在Python数据结构中的核心作用。

Rimo_Yee的博客 814

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

python实现hash表(上)

同理,get函数也先计算初始散列值,就是我在上面写的hashfunction()这个方法,用return返回给函数调用端使用,也就是计算机。它是将键和值关联起来的无序集合,其中的键是不重复的,键和值之间一一对应的关系。slots 与 data 它们是同步的,到后面我们进行get()和put(),操作的时候就会慢慢的领悟了。“slots的列表来储存键(key),而data的列表来存储值。这是使用字典来实现hash表,其最大优势是,给定一个键,很快就可以找到其关联的值。3.get(key)返回key对应的值。

2301_80246346的博客 790

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

Python字典与集合的底层实现:哈希冲突与动态扩容的性能影响

本文从CPython源码层面分析了dict和set的哈希表实现。Python 3.6+的紧凑字典通过索引表与entries表的分离设计,同时实现了插入顺序保持和内存效率。开放寻址法配合精心设计的二次探测序列,在负载因子不超过2/3时保持了O(1)的均摊查找和插入复杂度。动态扩容在容量翻倍边界处引入O(N)的重哈希开销,但在均摊意义上单次插入仍为O(1)。frozenset的哈希计算代价与元素数量线性相关,在高频用作字典键的场景下需要关注。

lady_mumu的博客 3786

hash表是怎么生成的?哈希表浅析

hash表的用途十分广泛,通俗来讲,hash表是一个用来存储key-value键值对的集合。 每一个键值对也叫做Entry,这些Entry会分散的储存在一个数组当中,这个数组就是HashMap的主干 python中有许多数据类型都是使用hash表实现的,比如字典,集合,计数器等。 接下来我们来实现一个简单的hash表,在写代码之前,我们先大致了解一下hash表是怎么储存数据的 例如有一个数据{‘a...

9527 1591

Redis设计与实现第一部分:第4章:字典、哈希表

  字典,又称为符号表(symbol table)、关联数组(associate array)或映射(map),是一种用于保存键值对(key-value pair)的抽象数据结构。   在字典中,一个键(key)可以和一个值(value)进行关联(或者说将键映射为值)。   字典中每个键都是独一无二的,可以通过键查找值,更新值,删除整个键值对等。   Redis使用的C语言没有内置这种数据结...

qq_34600232的博客 301

python通过字典实现映射_Python基础:映射(字典)

一、概述映射类型(Mapping Types)是一种关联式的容器类型,它存储了对象与对象之间的映射关系。字典(dict)是Python中唯一的映射类型,它是存储了一个个键值对(由键映射到值)的关联容器。其中,键(key)必须是可哈希的Python对象,而值(value)可以是任何Python对象。在功能上,Python中的字典类似于C++中的map。Python中最强大、最灵活的数据类型...

weixin_39992483的博客 2988

Python字典的底层原理

一文搞懂Python字典的底层原理。

qq_48441158的博客 2625

数据库索引:Hash索引

转载地址:https://www.jianshu.com/p/d0897bfdeedf Hash 本身是一个函数,又被称为散列函数,它可以帮助我们大幅提升检索数据的效率。打个比方,Hash 就好像一个智能前台,你只要告诉它想要查找的人的姓名,它就会告诉你那个人坐在哪个位置,只需要一次交互就可以完成查找,效率非常高。大名鼎鼎的 MD5 就是 Hash 函数的一种。 Hash 算法是通过某种确定性的算法(比如 MD5、SHA1、SHA2、SHA3)将输入转变为输出。相同的输入永远可以得到相同的输出,假设输入内

XiaoCai 6430
上一篇: 模拟python底层数据类型,大整数的实现!
下一篇: 递归讲解与递归实现列表的反转
我是py呀
博客等级 码龄8年 205粉丝 130原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值