数据结构与算法之八 队列

简介: 数据结构与算法之八 队列

视频课堂https://edu.csdn.net/course/play/7621


目标


在本章中,你将学到:

识别队列的特性

运用不同类型的队列

运用队列来解决编程问题

使用散列法存储和搜索数据

考虑这样一种情形,你要创建一个有以下请求集的应用程序:

应用程序可被应用于多用户的请求。

每次,仅处理一个请求。

先到的请求优先被处理。

然而,这些软件接受请求的速度要远大于处理请求的速度。

因此需要将请求存储在队列中直到被处理。

你如何解决此问题?

你可以通过以这样的方式存储请求来解决该问题,即以请求到达的顺序来获取请求。

称为队列的数据结构以数据的到达顺序来存储和获取它们。

队列也被称为先入先出队列(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 调度

邮件服务

键盘缓冲

电梯

散列的基本原理是将给定的键值转换成偏移地址以检索记录。

在散列中,键转换为地址是通过一个关系(公式)也就是散列函数来完成的。

散列函数为两个或多个键产生相同的散列值,这种情况称作冲突。

使用一个好的散列函数可以使冲突发生的可能性降至最小。



选择散列函数的两个原则标准是:

简单并且计算快速。

在地址空间中应该达到均衡的键分布。

可以使用各种技术来设计散列函数,它们是:

截取法

模块法

平方取中法

折叠法

冲突问题可以使用称为分离链的方法得到解决。


目录
相关文章
|
C语言
【数据结构】栈和队列(c语言实现)(附源码)
本文介绍了栈和队列两种数据结构。栈是一种只能在一端进行插入和删除操作的线性表,遵循“先进后出”原则;队列则在一端插入、另一端删除,遵循“先进先出”原则。文章详细讲解了栈和队列的结构定义、方法声明及实现,并提供了完整的代码示例。栈和队列在实际应用中非常广泛,如二叉树的层序遍历和快速排序的非递归实现等。
1022 9
|
7月前
|
前端开发 Java
java实现队列数据结构代码详解
本文详细解析了Java中队列数据结构的实现,包括队列的基本概念、应用场景及代码实现。队列是一种遵循“先进先出”原则的线性结构,支持在队尾插入和队头删除操作。文章介绍了顺序队列与链式队列,并重点分析了循环队列的实现方式以解决溢出问题。通过具体代码示例(如`enqueue`入队和`dequeue`出队),展示了队列的操作逻辑,帮助读者深入理解其工作机制。
249 1
232.用栈实现队列,225. 用队列实现栈
在232题中,通过两个栈(`stIn`和`stOut`)模拟队列的先入先出(FIFO)行为。`push`操作将元素压入`stIn`,`pop`和`peek`操作则通过将`stIn`的元素转移到`stOut`来实现队列的顺序访问。 225题则是利用单个队列(`que`)模拟栈的后入先出(LIFO)特性。通过多次调整队列头部元素的位置,确保弹出顺序符合栈的要求。`top`操作直接返回队列尾部元素,`empty`判断队列是否为空。 两题均仅使用基础数据结构操作,展示了栈与队列之间的转换逻辑。
|
10月前
|
存储 C语言 C++
【C++数据结构——栈与队列】顺序栈的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现顺序栈的基本运算。开始你的任务吧,祝你成功!​ 相关知识 初始化栈 销毁栈 判断栈是否为空 进栈 出栈 取栈顶元素 1.初始化栈 概念:初始化栈是为栈的使用做准备,包括分配内存空间(如果是动态分配)和设置栈的初始状态。栈有顺序栈和链式栈两种常见形式。对于顺序栈,通常需要定义一个数组来存储栈元素,并设置一个变量来记录栈顶位置;对于链式栈,需要定义节点结构,包含数据域和指针域,同时初始化栈顶指针。 示例(顺序栈): 以下是一个简单的顺序栈初始化示例,假设用C语言实现,栈中存储
506 77
|
9月前
|
算法 调度 C++
STL——栈和队列和优先队列
通过以上对栈、队列和优先队列的详细解释和示例,希望能帮助读者更好地理解和应用这些重要的数据结构。
233 11
|
9月前
|
DataX
☀☀☀☀☀☀☀有关栈和队列应用的oj题讲解☼☼☼☼☼☼☼
### 简介 本文介绍了三种数据结构的实现方法:用两个队列实现栈、用两个栈实现队列以及设计循环队列。具体思路如下: 1. **用两个队列实现栈**: - 插入元素时,选择非空队列进行插入。 - 移除栈顶元素时,将非空队列中的元素依次转移到另一个队列,直到只剩下一个元素,然后弹出该元素。 - 判空条件为两个队列均为空。 2. **用两个栈实现队列**: - 插入元素时,选择非空栈进行插入。 - 移除队首元素时,将非空栈中的元素依次转移到另一个栈,再将这些元素重新放回原栈以保持顺序。 - 判空条件为两个栈均为空。
|
10月前
|
存储 C++ 索引
【C++数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】
【数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】初始化队列、销毁队列、判断队列是否为空、进队列、出队列等。本关任务:编写一个程序实现环形队列的基本运算。(6)出队列序列:yzopq2*(5)依次进队列元素:opq2*(6)出队列序列:bcdef。(2)依次进队列元素:abc。(5)依次进队列元素:def。(2)依次进队列元素:xyz。开始你的任务吧,祝你成功!(4)出队一个元素a。(4)出队一个元素x。
420 13
【C++数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】
|
9月前
|
缓存 监控 算法
内网监控管理软件:PHP 语言队列算法揭秘
在数字化办公环境中,内网监控管理软件对企业的稳定运行和信息安全至关重要。本文深入介绍PHP中的队列算法及其在内网监控软件中的应用,包括监控数据收集、任务调度和日志记录等场景,通过代码示例展示其实现方法。队列算法可提高性能、保证数据顺序并实现异步处理,为企业提供高效的安全保障。
158 1
|
10月前
|
存储 C语言 C++
【C++数据结构——栈与队列】链栈的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现链栈的基本运算。开始你的任务吧,祝你成功!​ 相关知识 初始化栈 销毁栈 判断栈是否为空 进栈 出栈 取栈顶元素 初始化栈 概念:初始化栈是为栈的使用做准备,包括分配内存空间(如果是动态分配)和设置栈的初始状态。栈有顺序栈和链式栈两种常见形式。对于顺序栈,通常需要定义一个数组来存储栈元素,并设置一个变量来记录栈顶位置;对于链式栈,需要定义节点结构,包含数据域和指针域,同时初始化栈顶指针。 示例(顺序栈): 以下是一个简单的顺序栈初始化示例,假设用C语言实现,栈中存储整数,最大
221 9
|
10月前
|
C++
【C++数据结构——栈和队列】括号配对(头歌实践教学平台习题)【合集】
【数据结构——栈和队列】括号配对(头歌实践教学平台习题)【合集】(1)遇到左括号:进栈Push()(2)遇到右括号:若栈顶元素为左括号,则出栈Pop();否则返回false。(3)当遍历表达式结束,且栈为空时,则返回true,否则返回false。本关任务:编写一个程序利用栈判断左、右圆括号是否配对。为了完成本关任务,你需要掌握:栈对括号的处理。(1)遇到左括号:进栈Push()开始你的任务吧,祝你成功!测试输入:(()))
240 7