数据结构-map

数据结构-哈希算法

哈希原理

hash哈希是一种算法

  • y = hash(x) 给定一个x一定得到固定的y
  • x是输入,x取值范围称为输入空间,x是任意值,x是任意长度(go中字节序列)
  • y是输出,y取值范围称为输出空间,但输出内容是固定长度的(字节序列长度固定)
  • 输入是无穷个,但是固定字节的输出却能表示的状态是有限个
  • 一定存在xm、xn经过hash函数算出的y值一样,把不同x值求得y值一样的情况称为hash冲突,他们碰撞了
  • hash算法设计还要兼顾 高效 ,x一个微小的变化,哪怕是一个bit位的变化,也将引起结果y巨大的变化
  • hash不可逆,不能从结果反推输入值
  • 单向散列算法 不可逆
  • 用在KEY的计算上

哈希算法

  • MD5(Message Digest Algorithm 5)信息摘要算法5,输出是128位。运算速度叫SHA-1快

    • 用户密码存储
    • 上传、下载文件完整性校验
    • 大的数据的快速比对,例如字段很大,增加一个字段存储该字段的hash值,对比内容开是否修改
  • SHA(Secure Hash Algorithm)安全散列算法,包含一个系列算法,分别是SHA-1、SHA-224、SHA-256、SHA-384,和SHA-512。

    • 数字签名防篡改
    package mainimport ("crypto/sha256""fmt"
    )func main() {h := sha256.New()h.Write([]byte("abc"))// 提供字节流r := h.Sum(nil)s := fmt.Sprintf("%x", r)  // 把字节序列的每个字节以16进制显示fmt.Printf("%T %s %d \n", r, s, len(s))
    }
    []uint8 e4b0cf398b77ac6efb797544d268782dc7d082e59c4d1aff15f3ae661588f0eb 64 
    

    映射

    映射Map,也有语言称为字典

  • 长度可变

  • 存储的元素是key-value对(键值对),value可变

  • key无序不重复

  • 不可索引,需要通过key来访问

  • 不支持零值可用,也就是说,必须要用make或字面常量构造

  • 引用类型

  • 哈希表

内存模型

map采用哈希表实现。Go的map类型也是引用类型,有一个标头值hmap,指向一个底层的哈希表。

哈希表

  • 存储kv对,一个kv对称为一个元素,键值对entry、item

  • len表示元素的个数,即 kv对的个数,cap不能用

  • key 不能重复,无序

    • key按照某种先后顺序加入到map中,但是从哈希表中看不出顺序来
    • key是关键的,还有唯一的意思
    • 相同key会 去重
  • 引用类型

    • 有一个标头值
    • 有一个指针指向底层的hash表
  • 不支持零值可用

哈希表原理 y=hash(x)

开辟一块内存空间,分割出一个个“房间”,这个房间称为bucket桶,按照y值为“房间”编号
使用给出的x计算出对应的y值,可以按照某种关系计算出数据将被存储到的“房间号码”,将数据存
入该房间
即使是hash函数设计的好,数据分布均匀,但是存储的数据很多(超过负载因子),则需要扩容,
否则再加入数据后,冲突太多,引起效率低下

hash冲突

  • 房间有人占了,就重新找个空房间让客人住,这是开放地址法
  • 房间有人占了,就挤在同一个房间内,将值用链表存储在一起,这是链地址法,也称拉链法,Go语言采用,但做了一定的优化

理解:有key hash后的key value 三种

1、如果key相同 则hash后的key一定相同

2、key不相同但是存在hash后的key是相同的,也就是房间号是相同

我们可以理解hash后的key为房间号,hash冲突就是hash后的key是相同的,若hash就的key是相同的可以存放在一个房间里面,在这个房间里面可以放几个key-value对,若是查找这个key-value,先找到这个房间,在这个房间内在查找key

构造


func main() {var m1 map[string]int // nil,很危险。map不是零值可用fmt.Println(m1, m1 == nil)m1["t"] = 200 // panic,不可以
}
//结论:零值不可用,用var a map[int]int 零值是nil但是后面无法增加kv对
// 1 字面量
//字面量定义map[string]int{k1:v1} ,花括号表示字面量
func main() {var m0 = map[string]int{}  // 安全,没有一个键值对而已fmt.Println(m0)
}
map[]func main() {var m1 = map[string]int{"a": 11,"b": 22,"c": 33,}fmt.Println(m1)}
map[a:11 b:22 c:33]
//make
func main() {m2 := make(map[int]string) // 一个较小的起始空间大小//make(map[string]int) // 没有告诉未来容纳多少元素,先开辟较小空间,如果未来kv对较多,可能频繁扩容m2[100] = "abc"m3 := make(map[int]string, 100) // 分配足够容量来容纳100个元素,长度为0。为了减少扩容,可以提前给出元素个数fmt.Println(m2, m3)
}map[100:abc] map[]//结论:
make(map[string]int, 100) 表示为100个元素自动生成足够(内部按照算法生成)的空间   make(map[string]int, 100)  告诉未来容纳多少元素,先开辟合适的空间来存储这些kv对,注意一般空间大小别元素个数大一些    
var m0 map[string]int 这不是赋值语句,go语言零值可用,但是这是引用类型,所以是nil

新增或修改

func main() {var m = make(map[string]int)m["a"] = 11 // key不存在,则创建新的key和value对m["a"] = 22 // key已经存在,则覆盖valuefmt.Println(m)
}
map[a:22]

查找

使用map一般需要使用key来查找,时间复杂度为O(1)

func main() {var m = make(map[string]int)m["a"] = 11m["a"] = 22if _, ok := m["b"]; ok {fmt.Println("存在")} else {fmt.Println("不存在")}
}

key访问map最高效的方式

长度

// 返回kv对的个数
func main() {var m = make(map[string]int)m["a"] = 11m["a"] = 22fmt.Println(len(m))
}
1

注意:由于map的特殊构造,不能使用cap。

移除

func main() {var m = make(map[string]int)m["a"] = 11  m["b"] = 22fmt.Println(m)delete(m, "a")// 存在,删除kv对fmt.Println(m)}map[a:11 b:22]
map[b:22]
即便不存在删除也不会panic

遍历

func main() {var m = map[string]int{"a": 11,"b": 22,"c": 33,}for k, v := range m {fmt.Println(k, v)}
}
a 11
b 22
c 33

注意:map的key是无序的,千万不要从遍历结果来推测其内部顺序,因为key在内存中是乱序

排序sort

Go的标准库提供了sort库,用来给线性数据结构排序、二分查找。

升序

// 切片排序
// 针对int、string有快捷方法Ints、Strings
func main() {var a = []int{-1, 23, 5, 7, 4, 9}sort.Ints(a)// 就地修改原切片的底层数组// sort.Sort(sort.IntSlice(a)) // sort.IntSlice(a)强制类型转换以施加接口方法fmt.Println(a)// 默认升序
}
[-1 4 5 7 9 23]func main() {b := []string{"xyz", "a", "abc", "Ab", "X"}sort.Strings(b)fmt.Println(b)
}
[Ab X a abc xyz]    //根据ascill码排序

降序

降序和升序不同 升序在go中已经定义好了 只需要调用 但是降序不行 func main() {b := []string{"xyz", "a", "abc", "Ab", "X"}sort.Sort(sort.Reverse(sort.StringSlice(b)))  //Reverse取反fmt.Println(b)
}
[xyz abc a X Ab]

二分查找

前提:必须先排序,并且是升序

func main() {// 二分查找a := []int{-1, 23, 5, 9, 7}sort.Ints(a)// 二分查找,必须是升序// 二分查找的前提是 有序i := sort.SearchInts(a, 1)  fmt.Println(i)
}
1

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

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

相关文章

Spring Boot 邮件发送(五种类型的邮件)

邮件协议: SMTP、POP3、IMAP SMTP 协议全称为 Simple Mail Transfer Protocol,译作简单邮件传输协议,它定义了邮件客户端软件与 SMTP 服务器之间,以及 SMTP 服务器与 SMTP 服务器之间的通信规则。 用户先将邮件投递到腾讯的 SMT…

C#每天复习一个重要小知识day3:随机数的生成

目录 格式: 生成随机数: 生成一个0-100的随机数: 以下是更详细的代码示例: 在C#中,可以使用Random类来生成随机数。这个类提供了多种方法来生成不同类型的随机数。 格式: Random 随机变量名(r) new …

论文阅读 Forecasting at Scale (一)

最近在看时间序列的文章,回顾下经典 论文地址 项目地址 Forecasting at Scale 摘要1、介绍2、时间业务序列的特点3、Prophet预测模型3.1、趋势模型3.1.1、非线性饱和增长3.1.2、具有变化点的线性趋势3.1.3、自动转换点选择3.1.4、趋势预测的不确定性 摘要 预测是一…

暗物质探测器认知教学VR元宇宙平台打破传统束缚

“飞船正在上升,马上就冲出大气层了!”这是一位在1:1还原的神舟飞船返回舱内借助VR设备置身元宇宙世界,沉浸式体验升空全过程的游客兴奋地说道。不仅如此,在载人飞船训练期,元宇宙技术为航天员虚拟一个逼真的太空世界&…

vue3 iconify 图标几种使用 并加载本地 svg 图标

iconify iconify 与 iconify/vue 使用 下载 pnpm add iconify/vue -D使用 import { Icon } from "iconify/vue";<template><Icon icon"mdi-light:home" style"color: red; font-size: 43px" /><Icon icon"mdi:home-flo…

hosts.allow和hosts.deny配置

有个单机环境限制ssh登录&#xff0c;有多种方式&#xff0c;这里选择了配置hosts.allow和hosts.deny [rootdb ~]# more /etc/hosts.allow # # hosts.allow This file contains access rules which are used to # allow or deny connections to network services t…

shell脚本三

目录 一、循环语句 一、循环 二、for循环语句 1.列表循环 2.与c语言循环相似的for循环 3.使用for打印三角形以及乘法表 4.测试172.16.114.0网段存活的主机并将存活的主机IP地址写入文件中&#xff0c;未存活的主机放入另一文件中 三、while循环语句 四、until循环语句…

如何使用 Navicat 连接 GaussDB 主备版

Navicat Premium&#xff08;16.2.8 Windows版或以上&#xff09; 已支持对GaussDB 主备版的管理和开发功能。它不仅具备轻松、便捷的可视化数据查看和编辑功能&#xff0c;还提供强大的高阶功能&#xff08;如模型、结构同步、协同合作、数据迁移等&#xff09;&#xff0c;这…

浅析OKR的敏捷性

前言 OKR对于工作的提升有着一定的不可替代的作用。特别在敏捷方面。 OKR的敏捷性 OKR&#xff08;Objectives and Key Results&#xff09;是一种目标设定框架&#xff0c;它的敏捷性主要体现在以下几个方面&#xff1a; 公开透明 OKR要求完全公开透明&#xff0c;让每个员…

每日一练:质因数分解

1. 题目 从键盘输入一个整数&#xff0c;开始整数的质因数分解&#xff0c;最后打印出该整数的所有质因数。 2.解题思路 1&#xff09;初始化&#xff1a; 从最小的质数开始&#xff0c;将输入的整数不断除以质数&#xff0c;直到无法整除为止。   2&#xff09;循环&#x…

ansible的基本安装

目录 一、简介 1.ansible自动化运维人工运维时代 2.自动化运维时代 3.ansible介绍 4.ansible特点 二、ansible实践 1.环境 2.ansible管理安装 3.ansible被管理安装 4.管理方式 5.添加被管理机器的ip 6.ssh密码认证方式管理 三、配置免密登录 1.ansible自带的密码…

【grep】从html表格中快速定位某个数据

文章目录 1 背景2 参考知识2.1 grep2.2 HTML基础语言标签 3 解决方案 1 背景 在html中是一堆表格、图片、文字什么的&#xff0c;想从表格中提取关键词为“GJC”后对应的数字&#xff0c;怎么办呢&#xff1f; 逐个打开html文件&#xff0c;“ctrlF”搜一下&#xff0c;然后复…

vue项目中element-ui对话框el-dialog嵌套显示时多了一个遮罩层解决办法

在对话框里又嵌套了一个对话框展示时&#xff0c;多了一个遮罩层&#xff0c;如下图所示&#xff1a; 解决办法如下&#xff1a; 给对话框添加append-to-body 属性&#xff0c;参考以下代码&#xff1a; <el-dialog :visible.sync"dialogVisible" append-to-body …

所有产品都值得用AI再做一遍,让AGI与品牌营销双向奔赴

微软 CEO Satya Nadella 曾经说过&#xff1a;“所有的产品都值得用 AI 重做一遍。” AI 大模型的出现&#xff0c;开启了一个全新的智能化时代&#xff0c;重新定义了人机交互。这让生成式 AI 技术变得「触手可得」&#xff0c;也让各行业看到 AGI 驱动商业增长的更大可能性。…

ui设计师简历自我评价的范文(合集)

ui设计师简历自我评价的范文篇一 本人毕业于艺术设计专业&#xff0c;具有较高的艺术素养&#xff0c;平时注重设计理论知识的积累&#xff0c;并将理论应用到作品中。了解当下设计的流行趋势&#xff0c;设计注重细节、重视用户体验&#xff0c;对色彩搭配有着浓厚的兴趣&…

13、深度学习之神经网络

深度学习是机器学习中重要的一个学科分支,它的特点就在于需要构建多层“深度”的神经网络。 人们在探索人工智能初期,就曾设想构建一个用数学方式来表达的模型,它可以模拟人的大脑,大脑我们都知道,有很多神经元,每个神经元之间通过突触链接。 神经网络的设计就是模仿了这…

11.6AOP

一.AOP是什么 是面向切面编程,是对某一类事情的集中处理. 二.解决的问题 三.AOP的组成 四.实现步骤 1.添加依赖(版本要对应): maven仓库链接 2.添加两个注解 3.定义切点 4.通知 5.环绕通知 五.excution表达式 六.AOP原理 1.建立在动态代理的基础上,对方法级别的拦截. 2. …

3

目录 【任务 3】私有云运维开发[10 分] 【题目 1】Ansible 服务部署&#xff1a;部署 MariaDB 集群[2 分] 【题目 2】Ansible 服务部署&#xff1a;部署ELK 集群服务[2 分] 【题目 3】Python 运维开发&#xff1a;基于OpenStack Restful API 实现镜像上传[1 分] 【题目 4】Pyth…

【机器学习】贝叶斯分类器

贝叶斯分类器是一种概率模型&#xff0c;利用贝叶斯公式来解决分类问题。假设样本的特征向量服从一定的概率分布&#xff0c;我们就可以计算出该特征向量属于各个类的条件概率。分类结果是条件概率最大的分类结果。如果假设特征向量的每个分量彼此独立&#xff0c;则它是朴素贝…

Java,数据结构与集合源码,关于List接口的实现类(ArrayList、Vector、LinkedList)的源码剖析

目录 ArrayList ArrayList的特点&#xff1a; ArrayList源码解析&#xff1a; Vector Vector的特点&#xff1a; Vector源码解析&#xff1a; LinkedList LinkedList的特点&#xff1a; LinkedList的源码剖析&#xff1a; 使用说明&#xff1a; ArrayList ArrayList的…