您的位置:首页 > 理论基础 > 数据结构算法

数据结构与算法之八 队列

2016-06-12 22:01 393 查看
目标

在本章中,你将学到:
识别队列的特性
运用不同类型的队列
运用队列来解决编程问题
使用散列法存储和搜索数据

考虑这样一种情形,你要创建一个有以下请求集的应用程序:
应用程序可被应用于多用户的请求。
每次,仅处理一个请求。
先到的请求优先被处理。
然而,这些软件接受请求的速度要远大于处理请求的速度。
因此需要将请求存储在队列中直到被处理。
你如何解决此问题?
你可以通过以这样的方式存储请求来解决该问题,即以请求到达的顺序来获取请求。
称为队列的数据结构以数据的到达顺序来存储和获取它们。
队列也被称为先入先出队列(FIFO)。

一个队列就是含有一组元素的列,这个列中数据从队列一端添加,然后从队列另一端删除。

插入:指将数据添加到队列中。
假设希望将元素F添加到队列中。
因为添加操作发生在末端,元素F将添加到元素D之后。
现在元素F变成了末端。

删除:指的是将元素从队列中删除。
数据从前端被删除。因此,元素B将从队列中移走。
现在A变成了队列的前端。

问题描述:
考虑一个银行的场景。当客户来到柜台并输入请求,就可以得到一个请求号码。收到请求号码后,客户必须等候一段时间。客户请求需要进入系统队列,并按照到达的顺序获得处理。你需要实现一种适当的数据存储机制在系统中存储这些请求。

队列的应用



队列能在多个领域中得到应用,如:
打印机暂存
CPU调度
邮件服务
键盘缓冲
电梯

打印机暂存

打印机可能会在短时间内收到多个打印请求。
收到的打印请求频率要大于处理请求的频率。
因此,就需要一个临时存储机制来按照到达顺序存储打印请求。
在这种情况下,队列就是最佳选择,可以按照先到先服务原则存储打印请求。



CPU 调度

一个CPU同一时间只能处理一个请求。
通常,CPU接受请求的频率都大于处理请求的频率。
因此这些请求都按照到达顺序暂时存储在一个队列中。
当CPU有空时,就会从队列中一个个地取出请求,并处理它们。
一旦一个请求处理完后,就会从队列中移出。
CPU就会取出下一个请求,并处理。
在一个分时系统中(time sharing system),CPU分配给每个请求的时间都是固定的。

所有的请求都临时存储在队列中。
CPU一个个地按固定时间处理每个请求。
如果请求在固定时间段中处理完成,这个请求就会从队列中移出。
如果一个请求没有在特定的时间段中处理完成,就会被移到队列的末尾。
CPU就会处理队列中的下一个请求,依此类推。

邮件服务

在许多企业中,许多行为都是通过邮件进行的。
但如果邮件服务器下线了,并且还有人要给你发邮件,邮件就会退回给发件人。
要避免这样的情况,许多企业实现了一个邮件备份服务。
当邮件服务器发生问题时而导致邮件没有发送成功,这个邮件就被传送到一个备份服务器。
备份服务器将邮件临时存储在队列中。
当邮件服务器恢复工作时,所有的邮件会按到达的顺序发送给收件人。

键盘缓冲

队列还被用于存储你在键盘上的每一下敲击。
有时候你通过键盘敲击的数据并不是立即反映在屏幕上。
这是因为当时处理器忙于处理其他任务,无法处理你的请求。
在这种情况下,数据临时存储在队列中,直到处理器开始处理这个请求。
一旦处理器空闲下来,你所有的敲击都会按照到达的顺序显示在屏幕上。

电梯

一部电梯也使用队列来存储用户的请求。
假设电梯此时在第一层。有个用户在底层按了电梯按钮。同时另一个用户在二层也按了电梯按钮。
那么电梯会前去最先按钮的一层,也就是说,这些请求会按先到先服务的原则进行处理。
但是,如果一个用户在底层,另一个用户在九层(9层往↑往↓),那么无论谁先按钮,电梯都会先去底层,因为去底层的距离更短。这种情况下,将需要使用优先级队列。

执行散列搜索

二叉搜索算法有以下缺点:
它只能搜索排序过的列表。
它还需要一个方法能够直接访问列表的中间元素。
能够克服这些限制并且提供高效率的搜索算法是散列搜索。

散列有两个限制:
它可能导致冲突。
它不能顺序访问。

定义散列

假设您要搜索与给定记录列表中的某个给定键值相对应的记录。
要检索所需记录,需要顺序地搜索整个记录直到找到具有所需键值的记录。
该方法十分耗时,尤其当列表非常大的时候更加耗时。
一个有效的解决方法是在偏移地址的帮助下搜索该记录。
可以使用称为散列法的技术来计算记录的偏移地址。

散列的基本原理是将键值转换为偏移地址来检索记录。
键转换为地址是通过一种关系(公式)来完成的,就是散列
使用散列搜索记录的过程总结为:
1. 给定一个键,散列函数将它转换为范围从1到n的散列值(位置),其中
n 是已经为这些记录分配的存储(地址)空间的大小。
2. 在产生的位置处检索到记录。

散列有两个限制:
它可能导致冲突。
它不能顺序访问。

选择散列函数的两个原则标准是:
简单并且能够快速计算。
能够在地址空间中获取键的均匀分布。
设计一个散列函数有各种技术,其中有:
截取法
模块法
平方取中法
折叠法

解决冲突

试图将两个键存储在同一位置的情形称为冲突。
两个记录不能占用同一个位置。因此,需要注意发生冲突的情况。
冲突可以使用称为分离键的方法得到解决。

使用散列比使用其他搜索方法更快速。
散列效率在理想化的情况下是O(1)。
但是,由于冲突,散列的效率会降低。
在这种情况下,散列的效率取决于散列函数的质量。

小结

在本章中,你已经学到:
一个队列就是线型数据结构,队列中的元素被插入在队列末端,然后从队列前端删除。
队列上可进行的操作有插入和删除。
可通过使用数组或链接列表来实现队列。
一个使用循环数组实现的队列能克服线性数组实现的队列的空间利用率问题。
使用链接列表实现的队列也被称为链接队列。

队列能在多个领域中得到应用:
打印机暂存
CPU调度
邮件服务
键盘缓冲
电梯
散列的基本原理是将给定的键值转换成偏移地址以检索记录。
在散列中,键转换为地址是通过一个关系(公式)也就是散列函数来完成的。
散列函数为两个或多个键产生相同的散列值,这种情况称作冲突。
使用一个好的散列函数可以使冲突发生的可能性降至最小。

选择散列函数的两个原则标准是:
简单并且计算快速。
在地址空间中应该达到均衡的键分布。
可以使用各种技术来设计散列函数,它们是:
截取法
模块法
平方取中法
折叠法
冲突问题可以使用称为分离链的方法得到解决。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: