自定义实现hashmap-python

前文

​ 今天这篇文章给大家讲讲hashmap,这个号称是所有前后端工程师都会的数据结构。

hashmap基本结构

​ hashmap这个数据结构其实并不难,它的结构非常清楚,说白了就是一个定长的链表,这个数组的每一个元素都是一个链表。我们把这个结构画出来,大家一看就明白了。

img

headers是一个定长的数组,数组当中的每一个元素都是一个链表。我们可以遍历这个链表。数组是定长的,但是链表是变长的,所以如果我们发生元素的增删改查,本质上都是通过链表来实现的。

hashmap的get和put算法时间复杂度空间复杂度是多少?

  • get时间复杂度

    get最好情况:O(1)
    - get最坏情况:O(n),即链表查询的时间复杂度
    - get平均:O(1)

  • put时间复杂度

    • put最好情况:O(1)
    • put最坏情况:O(1),即链表尾部插入
    • put平均:O(1)
  • hashmap的空间复杂度

    O(M), M为map元素的个数,因为几乎每多一个元素就多一个空间储存,多一个桶或者在桶内多一个位置。

hashmap完整代码

class Node:def __init__(self, key, val, prev=None, next_=None):self.key = keyself.val = valself.prev = prevself.next_ = next_def __repr__(self):return str(self.val)class LinkedList:def __init__(self):self.head = Node(None, "header")self.tail = Node(None, "tail")self.head.next_ = self.tailself.tail.prev = self.headself.size = 0def append(self, node):prev = self.tail.prevnode.prev = prevnode.next_ = prev.next_prev.next_ = nodenode.next_.prev = nodeself.size += 1def delete(self, node):prev = node.prevnext_ = node.next_prev.next_, next_.prev = next_, prevself.size -= 1def delete_node_by_key(self, key) -> bool:node = self.head.next_while node != self.tail:if node.key == key:self.delete(node)return Truenode = node.next_return Falsedef get_list(self):ret = []cur_node = self.head.next_while cur_node != self.tail:ret.append(cur_node)cur_node = cur_node.next_return retdef get_node_by_key(self, key):cur_node = self.head.next_while cur_node != self.tail:if cur_node.key == key:return cur_nodecur_node = cur_node.next_return Noneclass HashMap:def __init__(self, capacity=16, load_factor=5):self.capacity = capacityself.load_factor = load_factorself.headers = [LinkedList() for _ in range(capacity)]def get_hash_key(self, key):return hash(key) & (self.capacity - 1)def _put(self, key, val):linked_list = self.headers[self.get_hash_key(key)]if linked_list.size >= self.capacity * self.load_factor:self.reset()linked_list = self.headers[self.get_hash_key(key)]node = linked_list.get_node_by_key(key)if node:node.val = valelse:linked_list.append(Node(key, val))def get(self, key, default=None):linked_list = self.headers[self.get_hash_key(key)]node = linked_list.get_node_by_key(key)if node is None and default:return defaultreturn nodedef __getitem__(self, item):if self.get(item):return self.get(item)raise KeyError("无效的key")def __setitem__(self, key, value):self._put(key, value)def keys(self):for head in self.headers:for node in head.get_list():yield node.keydef values(self):for head in self.headers:for node in head.get_list():yield node.valdef items(self):for head in self.headers:for node in head.get_list():yield node.key, node.valdef setdefault(self, key, default):if self.get(key):return defaultself._put(key, default)return Truedef delete(self, key) -> bool:linked_list = self.headers[self.get_hash_key(key)]return linked_list.delete_node_by_key(key)def reset(self):headers = [LinkedList() for _ in range(self.capacity * 2)]self.capacity = self.capacity * 2for linked_list in self.headers:nodes = linked_list.get_list()for node in nodes:hash_key = self.get_hash_key(node.key)linked_list_ = headers[hash_key]linked_list_.append(node)self.headers = headersif __name__ == '__main__':# 创建字典m1 = HashMap()# 添加键值对m1["name"] = "马亚南"m1["age"] = 18# 获取键对应的值print(m1["name"], m1.get("age"))# 获取字典的容量# print("capacity", m1.capacity)# 1268不会扩容,1269自动扩容,1280是桶分配绝对均匀的情况,也即是说16*80=1280# for i in range(1269):#     m1[i] = i * 10# print("capacity", m1.capacity)# 删除元素print(m1.delete("name"), "删除成功")# print(m1["name"])  # 此语句会抛出KeyError错误print(m1.get("name", "默认值-哈哈哈"))# setdefault设置,跟python的实现等价name = m1.setdefault("name", "王五")print(name, "-setdefault")# keysfor key in m1.keys():print(key)# valuesfor val in m1.values():print(val)# items:for key, val in m1.items():print(key, val)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/147083.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

司空见惯 - 奈尔宝的NTTP

联合国对21世纪人才定义的标准,包括六种核心技能,即批判性思维(critical thinking)、人际交往(communication)、与人合作(collaboration)、创造性(creativity)、信息素养(information literacy)…

DPDK程序结合网络助手接收数据

网络调试工具&#xff1a;https://download.csdn.net/download/hdsHDS6/88390999?spm1001.2014.3001.5503 DPDK代码&#xff1a; #include <stdio.h> #include <string.h> #include <rte_eal.h> #include <rte_ethdev.h> #include <rte_ip.h> …

【数据结构】红黑树(C++实现)

​ ​&#x1f4dd;个人主页&#xff1a;Sherry的成长之路 &#x1f3e0;学习社区&#xff1a;Sherry的成长之路&#xff08;个人社区&#xff09; &#x1f4d6;专栏链接&#xff1a;数据结构 &#x1f3af;长路漫漫浩浩&#xff0c;万事皆有期待 上一篇博客&#xff1a;【数据…

特斯拉被称为自动驾驶领域的苹果

特斯拉的自动驾驶技术无疑是居于世界上领先地位的,有人形容特斯拉是自动驾驶汽车领域的苹果。特斯拉发布的Tesla Vision系统只配备了摄像头,不依靠雷达。 这并不是特斯拉唯一和其它对手不同的地方,他们的整个战略都是基于车队和销售产品,而其大多数竞争对手则销售自…

对象创建与内存分配机制

对象的创建 对象创建的主要流程: 1.类加载检查 虚拟机遇到一条new指令时&#xff0c;首先将去检查这个指令的参数是否能在常量池中定位到一个类的符号引用&#xff0c;并且检查这个符号引用代表的类是否已被加载、解析和初始化过。如果没有&#xff0c;那必须先执行相应的类…

stm32 - 中断/定时器

stm32 - 中断/定时器 概念时钟树定时器类型基准时钟&#xff08;系统时钟&#xff09;预分频器 - 时基单元CNT计数器 - 时基单元自动重装寄存器 - 时基单元基本定时器结构通用定时器计数器模式内外时钟源选择 定时中断基本结构时序预分频器时序计数器时序 概念 时钟树 https:…

解决Invalid bound statement (not found)错误~

报错如下所示&#xff1a; 找了好久&#xff0c;刚开始以为是名称哪里写的有问题&#xff0c;但仔细检查了好多遍都不是 最后发现了问题如下所示&#xff1a; UserMapper里面的内容被我修改了&#xff0c;但classes中的内容还是原来的内容&#xff0c;所以才导致了编译器报错n…

Android 活动Activity

目录 一、启停活动页面1.1 Activity的启动和结束1.2 Activity的生命周期1.3 Activity的启动模式 二、在活动之间传递消息2.1 显式Intent和隐式Intent2.2 向下一个Activity发送数据2.3 向上一个Activity返回数据 三、补充附加信息3.1 利用资源文件配置字符串3.2 利用元数据传递配…

【Python】函数(function)和方法(method)的区别

这里先说结论&#xff0c;为了满足心急的小伙伴&#xff1a;method与function的最大区别就是参数有无进行绑定。 自定义类Test&#xff1a; 首先先来一个自定义类&#xff1a; class Test:def Func_normal(arg):print(Func_normal:,arg)staticmethoddef Func_static(arg):pri…

sentinel-dashboard-1.8.0.jar开机自启动脚本

启动阿里巴巴的流控组件控制面板需要运行一个jar包&#xff0c;通常需要运行如下命令&#xff1a; java -server -Xms4G -Xmx4G -Dserver.port8080 -Dcsp.sentinel.dashboard.server127.0.0.1:8080 -Dproject.namesentinel-dashboard -jar sentinel-dashboard-1.8.0.jar &…

【小尘送书-第六期】《巧用ChatGPT轻松玩转新媒体运营》AI赋能运营全流程,帮你弯道超车、轻松攀登运营之巅

大家好&#xff0c;我是小尘&#xff0c;欢迎你的关注&#xff01;大家可以一起交流学习&#xff01;欢迎大家在CSDN后台私信我&#xff01;一起讨论学习&#xff0c;讨论如何找到满意的工作&#xff01; &#x1f468;‍&#x1f4bb;博主主页&#xff1a;小尘要自信 &#x1…

1.5 计算机网络的类别

思维导图&#xff1a; 1.5.1 计算机网络的定义 我的笔记&#xff1a; #### 精确定义&#xff1a; 计算机网络没有统一的精确定义&#xff0c;但一种较为接近的定义是&#xff1a;计算机网络主要由一些通用的、可编程的硬件互连而成&#xff0c;这些硬件并非专门用来实现某一特…

【软件测试】自动化测试selenium(一)

文章目录 一. 什么是自动化测试二. Selenium的介绍1. Selenium是什么2. Selenium的特点3. Selenium的工作原理4. SeleniumJava的环境搭建 一. 什么是自动化测试 自动化测试是指使用软件工具或脚本来执行测试任务的过程&#xff0c;以替代人工进行重复性、繁琐或耗时的测试活动…

vue中 css scoped原理

Vue中css的逻辑是先放子组件&#xff0c;然后放父组件&#xff0c;所以同样的css类名&#xff0c;子组件会被父组件覆盖 html 如下 子被父覆盖 scoped是通过给组件加hash值&#xff0c;锁定组件。 父子组件均scoped的情况下&#xff0c;子仍会覆盖 还是被覆盖了 如何避免被…

Springboo整合Sentinel

Springboo整合Sentinel 1.启动Sentinel java -jar sentinel-dashboard-1.8.6.jar2.访问localhost:8080到Sentinel管理界面(默认账号和密码都是sentinel) 3.引入依赖(注意版本对应) <dependency><groupId>com.alibaba.cloud</groupId><artifactId>spr…

[Linux] 5.Linux虚拟机和Windows文件共享

一、拖拽 如果安装了VMware Tool可以从Windows直接拖进Linux中共享文件&#xff0c;通过拖拽的方式可以把文件从Linux 传输到Windows 二、 文件共享 需要安装VMware Tool点击添加&#xff0c;选择Windows文件的路径&#xff0c;名称作为Linux访问的路径 cd什么都不加&#xff…

PCB铺铜连接方式

在铺铜前先把栅格吸附关闭铺铜会流畅很多 在嘉立创专业版中&#xff0c;默认铺铜方式是这样 改变铺铜规则为直连 效果如下

leetCode 55.跳跃游戏 贪心算法

给你一个非负整数数组 nums &#xff0c;你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度。判断你是否能够到达最后一个下标&#xff0c;如果可以&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 示例 1&#xff1a; 输入…

操作系统--分页存储管理

一、概念介绍 分页存储&#xff1a;一是分内存地址&#xff0c;二是分逻辑地址。 1.分内存地址 将内存空间分为一个个大小相等的分区。比如&#xff0c;每个分区4KB。 每个分区就是一个“页框”&#xff0c;每个页框有个编号&#xff0c;即“页框号”&#xff0c;“页框号”…

字符检测专题第二期:通用、简单、快速,见证AI字符识别的超能力!

随着科技的不断进步&#xff0c;OCR&#xff08;光学字符识别&#xff09;技术在工业应用中扮演着越来越重要的角色。 在实际生产中&#xff0c;OCR技术可在生产流程监控、自动化设备控制、品质控制和物流控制等方面发挥作用&#xff0c;提高生产流水线的产量和质量&#xff0c…