什么是hash
hash表小栗子
hash表
在数据结构中被称之为散列表
,hash
在编程中用的非常多,可见之重要。
为什么很重要呢,我们来举个例子
加入我们有如下数据
假设要查询数据为26
的元素,你会怎么查询呢?
最简单的是 直接从 10、1、2...26 查询 6次查到数据 26 对吧
那么还有没有什么查询方法呢? 有的,我们可以定义一个函数,接收数据,函数返回的是 (数据 % 10)
这样,我们直接调用 函数就可以直接得到数据了,hash表
正是做这样的事情的。
hash 表定义
那么什么是hash表
,hash 表
可以通过key
来直接访问数据的数据结构,而我们上述定义的函数称之为 哈希函数 ,哈希函数 可以理解为 将数据映射为一个表,我们直接访问表中的位置,从而直接访问数据。
例如如上例子
我们hash表
为
我们的 哈希函数 为num % 10
,num
为我们要查询的数,通过函数我们能够直接得到下标,从而得到数据是否存在。
hash map 解决冲突的几种方式
为什么会有hash冲突
借上述例子
我们再插入一个 11 ,我们使用 哈希函数 应该插在 key 为 1 的位置
我们发现,一个key
对应多个值,我们到底应该判断哪个呢? 这个其实就是哈希冲突
如何避免hash冲突呢?
解决冲突方法
拉链法
我们可以给每个数组的value都定义一条链表,当遇到冲突的时候,直接新增一个节点就成了,例如,我们在上面的hash表中插入 11 , 若使用拉链法,我们得到的结果可以是这样的。
开放定址法
当hash冲突时,就去寻找离它最近的空的地址,有空的便存下,只要我们hash表足够大,我们就能够找到并且将数据存下。
其中这里又分为 线性探测 和 二次探测,就不多讲了
例如我们已经有如下hash表了
若我们再存入 22
,按照哈希函数,它应当存在 key
为2
的位置,但是改地址已经有值了,所以,它找一个离它最近的空间,比如 下标为3
这个为空的,就可以放进来
若此时,我们插入13
数据呢,同样的到底,它会找后面空的位置,即5
当查询的时候也一样,当查询不到的时候,顺着往后查找即可
建立公共溢出区
这种方法,先创建哈希表 和 公共溢出区表,先存hash表,若发生冲突了,则存公共溢出区区,查询亦然。
go map 语法
创建map
我们可以使用make
或者直接定义map
我们如上使用了
map1 := map[int]int{}
和var map2 = make(map[int]int)
创建了 map1
和 map2
其中,map[key的类型]值的类型 ,这个需要指定才行
我们运行一下程序看看
使用: go run main.go
访问map
我们可以直接通过key
来访问元素数据,例如,我们想求 map1[0]
和 map2[1]
数据,我们可以这样写
我们执行一下,查看能否获取数据呢
遍历map
我们可以使用for k,v := range map
的形式来遍历map
,例如,我们遍历一下 map1
注意,map是输出是无序的,我们尝试多输出几次
删除map元素
我们可以直接使用delete
删除map
元素,例如
我们尝试执行一下
可见,key: 1
已经被删除了
判断map是否存在
我们可以使用 _ , ok := map1[key]
若存在,则ok
为 true
,若不存在,ok
为false
我们尝试下
map小实验
我们写个小程序,来做一下map
的实验,该实验是统计文件单词的个数
例如,有如下文件
写起来不难,我们看看
我们尝试运行输出以下
若想要排序,直接使用sort
即可(偷懒了偷懒了)
思考
关于go map
就这样吧,本来想看看go map
底层的,结果我找了一下资料,也看了一部分源码,奈何自身强度不行,看不懂,只得暂时搁置,后面把go
基础看完了,再回过头来看底层源码吧,加油,运维小学生。