哈希表的存储是由键(key)和值(value)组成的数据。
例如我们对多个人的性别进行存储,key值是人的姓名,value值是人的性别。
let arr = [
"Joe":"M",
"Sue":"F",
"Dan":"M",
"Nell":"F",
"Ally":"F",
"Bob":"M",
]
上面代码,为了和哈希表进行对比,先将数据存储到数组中去。
假设一种场景,我们要找到Ally的性别,按照数组的操作,我们从下标为0的位置开始找姓名为Ally的,依次往下,下标为0123时候都不是Ally,直到下标为4的时候,我们把键对应的值取出就知道Ally的性别为F(女)了。
数据量越多,线性查找耗费的时间就越长。由此可知道:由于数据查询比较耗时,所以此处并不适合使用数组来存储数据。
但是使用哈希表便可以解决这个问题。首先准备好数组,我们用一个长度为5的数组来存储数据。
哈希表存储数据流程:
先存第一个人的姓名Joe和性别M,
步骤:1.使用哈希函数(Hash)计算Joe的键,也就是字符串“Joe”的哈希值。得到的结果是4928.
2.将得到的值4928除以数组长度5,记作4928 mod 5 = 3. 所得的余数是3。
3.所以最终Joe的运算结果是3,因此我们将Joe的数据存入下标数组下标是3的位置。
对于arr中的所有信息都操作以上步骤。
但是这样事情还没结束
冲突
Nell的哈希值是6276 ,mod 5 的结果是1.Sue的哈希值是7291,mod 5的结果也是1.这种存储位置重复了的情况叫做“冲突”。遇到这种情况,可以使用链表在已有的数据后面继续存储新的数据。
//个人思考:在这里来看,原有设定的数组类型就不属于真正意义上的数组,因为传统意义上的数组中的每个元素的类型是一样的。
//而这种结构既存储字典,又存储链表的类型属于哈希表。
//swift中的元组也是能存储多种类型的数据结构,只是不知道有没有区别
//传统意义上的数组中第3个位置不存数据,第四个位置存数据不知道会发生异常情况吗
当数据存储完毕之后,用来存储数据的这个特殊的数组叫做哈希表。
哈希表的数据查询方法:
如果我们想要查询Dan的性别,先计算Dan的哈希值,然后对其进行mod运算。最后得到的结果是4.
于是我们直到它存储在下标为4的位置。直接就得出Dan的性别为M。
如果我们想要查询Ally的性别,同样的方法计算出来位置,最终发现3号下标的位置存储的不是Ally而是Joe,此时我们就需要队Joe所在的链表进行线性查找。
由此才能查找到键值为Ally的数据。便知道Ally的性别为女性(F)。
总结:
在哈希表中,我们可以利用哈希函数快速访问到数组中的目标数据。如果发生哈希冲突,就用链表进行存储。这样一来,不管数据量多大,我们都能灵活应对。
如果数组空间太小,使用哈希表容易发生冲突,线性查找的频率会更高。
如果数组空间太大,就会出现很多的空的下标,造成内存的浪费。
因此,给数组设定合适的空间非常重要。
其他应用场景
因为哈希表在数据存储上的灵活性和数据查询的高效性,编程语言的关联数组等也常常会使用到它。
网友评论