Python字典的底层原理

本文详细解释了Python字典的底层数据结构——哈希表,包括哈希函数的作用、哈希冲突的概念,以及如何通过开链法和开发寻址法解决冲突。还介绍了自定义实现的简单字典和解决哈希冲突的版本,以及自动扩容的设计。
摘要由CSDN通过智能技术生成

一,字典的底层数据结构

Python字典主要功能是存储键值对形式的数据,底层实现为哈希表,
同样实现的编程语言还有Java,JavaScript等。
python字典通过唯一key值找到value的时间复杂度为O(1),这得益于哈希表的特性。

二,哈希表(散列表)

哈希函数

首先介绍哈希函数,他可以将任意长度的数据映射为128位的编码,
是实现各种索引加速的强有力手段,
常见哈希函数包括MD5,SHA-1,SHA-256等,主要应用场景有安全加密,唯一标识,数据校验,
散列函数也就是接下来要介绍的哈希表的实现。

哈希表

用顺序表存储键值对,通过哈希函数计算出key对应的索引,将值存到索引对应的数据区中。
获取数据时,通过哈希函数计算出key对应的索引,取出索引位置对应的数据。
由于需要哈希函数计算,所以key值必须是可哈希的,也就是说key值必须是不可变的类型
python中不可变数据类型为:字符串,数字,元组(元素为不可变类型),函数,类对象

哈希表存储

hash表利用hash函数计算出Key的哈希值,与数组长度求余,取余结果index作为数组下标
list[hash(key)%len(list)]=value

三,哈希冲突与扩容

只要样本足够大,任何哈希函数一定会出现两个不同的key得出同一个哈希值,此时会出现两个不同key存入同一个数组位置,这种就称为哈希冲突。
可以利用开链法和开发寻址法解决冲突。

开链法:哈希表中的顺序表的每个位置存储的是链表,如果发生冲突时,冲突的元素会被加在链表的后面
开发寻址法:如果发现index位置上有数据,则探查新的位置来存储,index有值,则探查index+n 以此类推
主流编程语言的哈希冲突算法为开链法,比如java,python。

负载因子 表示散列表的装满程度       元素个数/散列表长度
当哈希表的存储位置存满后将会自动扩容,但是会在负载因子达到一定阈值时,
就会开始扩容,每次扩容大小为原来的两倍,java,python哈希表负载因子默认为0.75

四,手写字典

简单版字典

class myDict:
    def __init__(self,max):
        self.max=max
        self.hashTable=[None for _ in range(max)]
    def addItem(self,key,value):
        """增加"""
        index=hash(key)%self.max
        self.hashTable[index]=value
    def getValue(self,key):
        index=hash(key)%self.max
        return self.hashTable[index]
mydict=myDict(20)
mydict.addItem("key1",100)
mydict.addItem("key1",200)
mydict.addItem("key2",300)
print(mydict.getValue("key1"))
print(mydict.getValue("key2"))
print(mydict)

模拟哈希冲突

class myDict:
    def __init__(self,max):
        self.max=max
        self.hashTable=[None for _ in range(max)]
        self.capacity=0
    def addItem(self,key,value):
        """增加"""
        if self.capacity==self.max:
            raise Exception("超出容量")
        index=hash(key)%self.max
        if self.hashTable[index]:
            raise Exception(f"哈希冲突")
        self.hashTable[index]=value
        self.capacity+=1
    def getValue(self,key):
        index=hash(key)%self.max
        return self.hashTable[index]

"""模拟哈希冲突"""
mydict=myDict(100)
temp=['q','w','e','r','t','y','u','i','o']
result=[]
for x in temp:
    for y in temp:
        for z in temp:
            result.append(f"{x}{y}{z}")

for item in result:
    mydict.addItem(item,f"{item}-value")

解决哈希冲突版字典

#编写链表数据结构
class Node:
    """一个简单的链表子节点"""
    def __init__(self,key,value):
        self.key=key
        self.value=value
        self.next=None
class myDict:
    def __init__(self,max):
        self.max=max
        self.hashTable=[None for _ in range(max)]
        self.capacity=0
    def addItem(self,key,value):
        """增加"""
        if self.capacity==self.max:
            raise Exception("超出容量")
        index=hash(key)%self.max
        if self.hashTable[index]:
            print(f"hash冲突 {key} {value}")
            node=self.hashTable[index]
            while node.next:
                node=node.next
            node.next=Node(key,value)
        else:
            self.hashTable[index]=Node(key,value)
            self.capacity+=1
    def getValue(self,key):
        flag=False
        index=hash(key)%self.max
        node=self.hashTable[index]
        if not node:
            raise Exception("key error 1 ")
        elif node.key==key:
            return node.value
        else:
            while node.next:
                node = node.next
                if node.key==key:
                    flag=True
                    break
        if not flag:
            raise Exception("key error 2 ")
        return node.value

mydict=myDict(20)
temp=['q','w','e','r','t','y','u','i','o','a','s','d','f','g','h','j','k','z','x','c','v','b','n']
result=[]
for x in temp:
    for y in temp:
        for z in temp:
            result.append(f"{x}{y}{z}")

for item in result:
    mydict.addItem(item,f"{item}-value")
print(mydict)

自动扩容版字典

class Node:
    """一个简单的链表子节点"""
    def __init__(self,key,value):
        self.key=key
        self.value=value
        self.next=None
class myDict:
    def __init__(self,max):
        self.max=max
        self.hashTable=[None for _ in range(max)]
        self.capacity=0
    def addItem(self,key,value):
        """增加"""
        """判断是否需要扩容"""
        factor=self.capacity/self.max
        if factor>0.75:
            self.hashTable.extend([None for _ in range(self.max)])
            self.max=self.max*2
        index=hash(key)%self.max
        if self.hashTable[index]:
            print(f"hash冲突 {key} {value}")
            node=self.hashTable[index]
            while node.next:
                node=node.next
            node.next=Node(key,value)
        else:
            self.hashTable[index]=Node(key,value)
        self.capacity+=1
    def getValue(self,key):
        flag=False
        index=hash(key)%self.max
        node=self.hashTable[index]
        if not node:
            raise Exception("key error 1 ")
        elif node.key==key:
            return node.value
        else:
            while node.next:
                node = node.next
                if node.key==key:
                    flag=True
                    break
        if not flag:
            raise Exception("key error 2 ")
        return node.value

mydict=myDict(20)
temp=['q','w','e','r','t','y','u','i','o','a','s','d','f','g','h','j','k','z','x','c','v','b','n']
result=[]
for x in temp:
    for y in temp:
        for z in temp:
            for k in temp:
                for t in temp:
                    result.append(f"{x}{y}{z}{k}{t}")

for item in result:
    mydict.addItem(item,f"{item}-value")

print(mydict)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值