有“先进后出”这种数据结构,相应的也就会有“先进先出”的数据结构,那就是队列。
队列是一种特殊的受限制的线性表。
队列(queue)是只允许在一端进行插入操作,而在另一端进行删除操作的线性表。
队列是一种先进先出的(First In First Out)的线性表,简称 FIFO。允许插入的一端为队尾,允许删除的一端为队头。队列不允许在中间部位进行操作!假设队列是 q=(a1,a2,……,an),那么 a1 就是队头元素,而 an 是队尾元素。我们删除时,总是从 a1 开始,而插入时,总是在队列最后。这也比较符合我们通常生活中的习惯,排在第一个的优先出列,最后来的当然排在队伍最后。如下图:
用PHP数组模拟一个“队列”:
可以用函数:
array_push()和array_shift() 数组尾进,数组头出
array_unshift()和array_pop() 数组头进,数组尾出
代码很简单,楠神这里不做演示了。
说说队列数据结构的用处:
队列的用处是非常广泛的,就简单地说一个,可能我们做PHP会遇到的,那就是抢购系统。
现在购物平台都会有抢购商品的活动,如果平台很火,抢购的瞬间会是网站并发流量的高峰,这会对平台系统是一个大的挑战。
假如一个商品只卖100件,有一万个人同时购买(不是绝对同时,肯定会有先后顺序,只是时间差很细微),这个时候就不能直接操作数据库去实现抢购功能了。
数据库是怎么操作呢?
用户1从数据库获取库存数量,发现库存不为0,生成订单,库存减一。接着用户2、用户3……用户100,可能用户101获取库存量还不为0,然后用户101订单也生成成功了。像这种情况属于高并发下的“超卖”现象,因为操作数据库没有加锁,就会产生超卖。原因假设:用户100获取库存假设是1,它还没来得及把库存修改为0,用户101已从数据库获取库存了,获取的数字是1,所以就产生超卖了。防止超卖我们需要对数据库操作时开启事务加锁,确保数据安全。那问题又会出现,加锁后数据库性能会下降得很厉害,不足以支撑高并发,所以抢购功能不适合直接操作数据库。
数据库的数据毕竟是存在硬盘上,操作数据库就是操作硬盘IO读写。我们都知道在内存对数据读写比硬盘快得多,所以在高并发下直接在内存操作更适合。
在内存里需要用到队列这样的数据结构,把前100名放到队列里,只有队列里的用户才可以购买,这样解决抢购功能要省资源的多。
在内存里怎么把用户放入队列?这个不用我们自己写代码,以后我们会学习到redis,它就有队列的功能,依靠它就可以实现抢购的功能。
很多朋友对数据库还不怎么了解,没关系,我们马上就进入数据库MySQL学习阶段了。