开发者学堂课程【Go 语言核心编程 - 数据结构和算法: 数据结构和算法-哈希表(散列)1】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/627/detail/9865
数据结构和算法-哈希表(散列)1
一、哈希表(散列)
1、实际的需求:
Google 公司的一个上机题:
有一个公司,当有新的员工来报道时,要求该员工的信息加入(id,性别,年龄,住址..),当输入该员工的 id 时,要求查找到该员工的所有信息。
要求:不使用数据库,尽量节省内存,速度越快越好=>哈希表(散列)
前提是自己设计
2、哈希表的基本介绍:
散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。
如果把哈希表存放起来,就能自己做一个内存数据库,而且根据需求可以自己定制,如果不会这个,就只能用原始的一些方法去做。
哈希表的一个简单构造示意图:
一共十六根链表,不同的 id 分散到不同的链表去,在添加的过程中,按照从小到大的顺序。像0号链表,其中的 id 就是从小到大排列的。
3、使用 hashtable 来实现一个雇员的管理系统[增删改查]
>应用实例 google 公司的一个上机题:
有一个公司,当有新的员工来报道时,要求将该员工的信息加入(id,性别,年龄,住址..),当输入该员工的 id 时,要求查找到该员工的所有信息。
要求:
(1)不使用数据库,尽量节省内存,速度越快越好=>哈希表(散列)
(2)添加时,保证按照id从低到高插入
>思路分析:
(1)使用链表来实现哈希表,该链表不带表头
【即:链表的第一个结点就存放雇员信息】
(2)思路分析画出示意图
(3)代码实现[增删改查(显示所有员工,按id查询)]
主要完成增加和查询
>基于 hashtable 的雇员关系系统的思路分析:
(1)首先先建一个结构体,会出现一个含有七个链表的数组。
(2)七个元素分别是:LinkArr[0]、LinkArr[1]等等。
(3)hashtable 是一个结构体:
struct{LinkArr[7]EmpLink}
(4)、EmpLink 是一个雇员链表结构体:
struct{Head * Emp}
(5)、雇员与雇员之间会形成链表,其 id 会从小到大进行设计。
(6)、id 的结构体:
struct Emp{Id int Name string Next * Emp}
,它实际上指的是雇员图层。
(7)、每一个链表里面含有一个指向雇员的指针。
蓝色代表的是链表数组(一共有七个),里面的框是元素。元素里面具体放的是雇员链表。后面橙色框是代表的雇员他们会形成一共链表,而且他们的id 会从小到大进行排列。查询时也是在七个链表中找,而不是一整个数据库去找。橙色也是一个个结构体,一个个雇员信息,也是指向下一个节点的指针。
要完成这样的思路:首先要有一个哈希表,里面存了七个链表,他是一个链表数组,而且每一个链表里面指向一个雇员链表,这个链表里面有一个指向雇员的指针,通过这些来完成增删改查。
打个比方:比如现在有一根链表,这个链表里面有1000个雇员,这个里面没有散例,且只有一根链表,其中要查询id 为998的,如果是单链表的话就要一个个查,需要查998次才能查到,但是如果是用这个方法,就可以在存的时候输入998%7=?,那么在插入的时候就知道这个998是在某一个链表中,再查的时候就能找到998的位置,在指定的链表中查,这样时间就减少了很多,查询速度变快了。他的价值在于可以提高速度,在开发的时候用这样的方法,速度就大大提升了。
例如:
假设同时在线人数1000万,传统的方法就是操作数据库。如果按传统方法操作数据库,后果就是有一个人的状态发生了变化,或者有一个人要来读取一个ID的状态,那用户只能操作输入,这个量是很大的,对数据库的冲击很大。但是如果做一个优化,维护用户的状态。假设每个人都去操作数据库,这个数据库压力太大了,换一个思路,因为知道用户的状态不是一个特别重要的数据。因为用户状态可能会是离线在线或者版本,不是特别重要必须入库的数据。我们就可以采取做一个结构体。比如:
struct userState{id int state byte}
用2000个这个列表把它串起来。那这样的效果的好处,虽然可能会浪费一点内存,但是在操作一个用户的状态的时候,不管是修改还是查询速度都会变快。