「这是我参与11月更文挑战的第6天,活动详情查看:2021最后一次更文挑战」。
本来想取名为《前端算法入门》的,但是又担心自己水平不够把大家带沟里了,所以此系列文章就改名为和我一起学习前端算法
今天来讲讲大家经常听到的 栈 & 队列 和散列
栈 & 队列
这俩放在一起,因为这俩差不多,而且特别简单。 栈是“先进后出”,队列“先进先出”。 两者都可以使用数组或者链表来实现。 如果是用数组来实现,可以简单的这样理解:push/pop 为 入栈/出栈、push/shift 为 入队/出队。
散列
散列就比较有意思了。
散列表(Hash table,也叫哈希表),是根据键(Key)而直接访问在内存储存位置的数据结构。也就是说,它通过计算出一个键值的函数,将所需查询的数据映射到表中一个位置来让人访问,这加快了查找速度。这个映射函数称做散列函数,存放记录的数组称做散列表。
看到这你是不是按捺不住要发言了:这不就是 JS 中的对象嘛?
是,但又不完全是。
根据规范 6.1.7 The Object Type. 对象是键值对的集合,并且键只能是 String 或者 Symbol 类型,具体需要如何实现并没有规定。但是一般浏览器厂商都是基于哈希表来实现这种数据结构的。
也就是说,我们经常用的 ”对象“ 类型,其实是一个阉割版的哈希表,因为键的类型做了限制。
这个时候就可以很好的理解我之前这篇文章 和我一起学习前端算法 ——数据结构☞数组 中,提到的:数组在使用了不同的内部实现为什么会造成性能差异,因为当一个数组的内部实现 “退化” 成了对象时,就得进行哈希操作,步骤多了慢了也就不奇怪了。
散列原理
我们现在已经知道了散列可以使用键来访问/存储一个值,操作速度非常快。那么它是怎么实现的呢?
首先,在之前介绍过的几种数据结构中,数组无疑是查询效率最高的,可以根据下标进行元素的随机访问。
而散列表也是利用了数组的访问速度来实现的。
这时候可能就有同学要说了:你骗人,数组的下标都是数字,散列表的键名用的是字符串,字符串又不能当作索引。
说的不错,字符串的确不能直接当作索引。但是你考虑这样一个场景,我们打工人一般都会有一个工号,例如法外狂徒的工号是 9527,那我们现在说:9527,来前台拿一下你的女装,那是不是张三就知道是喊他去拿女装呢?
同样的道理,我们用某种不为人知的方法,将每个散列的 “key” 都转换成一个数字,这样不就可以用数组将他们存起来了嘛。而这个方法我们就叫做 哈希函数 也叫 散列算法、 散列函数 ,是一种从任何一种数据中创建小的数字“指纹”的方法。
在不同的语言中,哈希函数的实现方式是不同的,具体 JS 中的哈希是如何实现的我们可以不同深究,只要知道这么一回事就行。
结语
JS 的对象就是基于散列来实现的,所以我们经常可以见到使用对象来做字典加快访问速度的操作。但是对于一些特殊情况,比如需要区分键名 “数字1” 和 “字符串 '1' “ ,或者需要使用一个对象来做键名,则需要使用更专业的选手: Map 。
了解完了栈、队列以及散列,接下来再了解一下大名鼎鼎的 “树”。
本文为系列文章,将和大家一起逐步的学习前端算法相关知识。
系列所有文章都将收录在 专栏 里方便大家查看,大家可以关注我或者收藏本专栏。