第3章 表、栈和队列

3.4 队列ADT

        像栈一样,队列(queue)也是表。然而,使用队列时插入在一端进行而删除则在另一端
进行。

3.4.1 队列模型

队列的基本操作是Enqueue(入队)一它是在表的末端(叫作队尾(rear))插入一个元素,还有Dequeue(出队)——它是删除(或返回)在表的开头(叫作队头(front))的元素。图3-56显示一个队列的抽象模型。

3.4.2 队列的数组实现

        如同栈的情形一样,对于队列而言,任何表的实现都是合法的。像栈一样,对于每一种操作,链表实现和数组实现都给出快速的\mathit{O(N)}运行时间。队列的链表实现简单明了,留作练习。现在我们讨论队列的数组实现。
        对于每一个队列数据结构,我们保留一个数组Queue[]以及位置Front和Rear,它们代表队列的两端。我们还要记录实际存在于队列中的元素的个数size。所有这些信息是作为一个结构的一部分,除队列例程本身外通常不会有例程直接访问它们。下图表示处于某个中间状态的一个队列。顺便指出,图中那些空白单元有着不确定的值。尤其是前三个单元含有曾经属于该队列的元素。

        为了使一个元素X入队,我们让Size和Rear增1,然后置Queue[Rear]=X。若使一个元素出队,我们置返回值为Queue[Front],Size减1,然后使Front增1。也可能有其他的策略(将在后面讨论)。现在论述错误的检测。这种实现存在一个潜在的问题。经过10次入队后队列似乎是满了,因为Rear现在是10,而下一次再入队就会是一个不存在的位置。然而,队列中也许只存在几个元素,因为若干元素可能已经出队了。像栈一样,即使在有许多操作的情况下队列也常常不是很大。
        简单的解决方法是,只要Front或Rear到达数组的尾端,它就又绕回到开头。下图显示在某些操作期间的队列情况。这叫作循环数组(circular array)实现。
        实现回绕所需要的附加代码是极小的(虽然它可能使得运行时间加倍)。如果Front或Rear增1后超越了数组规定的大小,那么其值就要重置为数组的第一个位置。

        关于队列的循环实现,有两件事情要警惕。第一,检测队列是否为空是很重要的,因为当队列为空时,一次Dequeue操作将不知不觉地返回一个不确定的值。第二,某些程序设计人员使用不同的方法来表示队列的队头和队尾。例如,有些人并不用一个单元来表示队列的大小,因为他们依靠的是基准情形,即当队列为空时Rear=Front-1。队列的大小是通过比较Rear和Front隐式算出的。这是一种非常隐秘的方法,因为存在某些特殊的情形,因此,如果你需要修改用这种方式编写的代码,那么就要特别仔细。如果队列的大小不是结构的一部分,那么若数组的大小为ASize,则当存在ASize-1个元素时队列就满了,因为只有ASize个不同的大小值可区分,而0是其中的一个。采用任意一种你喜欢的风格,但要确保你的所有例程都是一致的。由于队列的实现方法有多种选择,因此如果你不使用size字段,那就有必要在代码中插入一些注释。

        在Enqueue的次数肯定不会大于队列的大小的应用中,使用回绕是没有必要的。像栈一样,除非主调例程肯定队列非空,否则Dequeue很少执行。因此对这种操作,只要不是关键的代码,错误的调用常常被跳过。一般说来这并不是无可非议的,因为你可能得到的时间节省量是极小的。
我们通过编写某些队列的例程来结束本节,其余例程留作练习。首先,在图3-57中给出队列的声明。正如对于栈的数组实现所做的那样,我们添加一个最大大小的域。还需要提供例程CreateQueue和DisposeQueue。此外,我们还需要提供测试一个队列是否为空的例程以及构造一个空队列的例程(见图3-58和图3-59)。读者可以编写函数IsFull,用于实现判断队列是否满了的功能。注意,Rear在Front之前预初始化为1。我们将要编写的最后的操作是Enqueue例程。严格遵循上面的描述,图3-60展示了队列的数组实现。

#ifndef _Queue_hstruct QueueRecord;
typedef struct QueueRecord *Queue;int IsEmpty(Queue Q);
int IsFull(Queue Q);
Queue CreateQueue(int MaxElements);
void DisposeQueue(Queue Q);
void MakeEmpty(Queue Q);
void Enqueue(ElementType X, Queue Q);
ElementType Front(Queue Q);
void Dequeue(Queue Q);
ElementType FrontAndDequeue(Queue Q);#endif   /*_Queue_h*/#define MinQueueSize (5)struct QueueRecord
{int Capacity;int Front;int Rear;int Size;ElementType *Array;
};

int IsEmpty(Queue Q)
{return Q->Size == 0;
}

void MakeEmpty(Queue Q)
{Q->Size = 0;Q->Front = 1;Q->Rear = 0;
}

static int Succ(int Value, Queue Q)
{if (++Value == Q->Capacity)Value = 0;return Value;
}void Enqueue(ElementType X, Queue Q)
{if (IsFull(Q))Error("Full queue");else{Q->Size++;Q->Rear = Succ(Q->Rear, Q);Q->Array[Q->Rear] = X;}
}

3.4.3 队列的应用

        有几种使用队列来提高运行效率的算法。它们当中有些可以在图论中找到,我们将在第9章讨论它们。这里,先给出某些应用队列的例子。

        当作业送交给一台行式打印机,它们就按照到达的顺序排列起来。因此,送往行式打印机的作业基本上被放到一个队列中。

        实际生活中的每次排队都(应该)是一个队列。例如,在一些售票口排列的队都是队列,因为服务的顺序是先到的先买票。

        另一个例子是关于计算机网络的。有许多种PC网络设置,其中磁盘是放在一台叫作文件服务器的机器上的。使用其他计算机的用户是按照先到先使用的原则访问文件的,因此其数据结构是一个队列。

        进一步的例子如下:

  • 当所有的接线员忙得不可开交的时候,对大公司的传呼一般都被放到一个队列中。
  • 在大学里,如果所有的终端都被占用,由于资源有限,学生们必须在一个等待表上签字。在终端上登录时间最长的学生将首先被强制离开,而等待时间最长的学生则将是下一个被允许使用终端的用户。

        处理用概率的方法计算用户排队预计等待时间、等待服务的队列能够排多长,以及其他一些诸如此类的问题将用到被称为排队论(queueing theory)的完整数学分支。问题的答案依赖于用户加入队列的频率以及一旦用户得到服务时处理服务花费的时间。这两个参数作为概率分布函数给出。在一些简单的情况下,答案可以解析算出。一种简单的例子是一条电话线有一个接线员。如果接线员忙,打来的电话就被放到一个等待队列中(这还与某个容许的最大限度有关)。这个问题在商业上很重要,因为研究表明,人们会很快挂上电话。

        如果我们有k个接线员,那么这个问题解决起来要困难得多。解析求解困难的问题往往使用模拟的方法求解。此时,我们需要使用一个队列来进行模拟。如果k很大,那么我们还需要其他一些数据结构来使得模拟更有效地进行。在第6章将会看到模拟是如何进行的。那时我们将对k的若干值进行模拟并选择能够给出合理等待时间的最小的k。

        正如栈一样,队列还有其他丰富的用途,这样一种简单的数据结构竟然能够如此重要,实在令人惊奇。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/209933.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

前端组件库开发

通常我们会使用很多组件库,有时候我们会去看源码比如element,antd,然后发现多少是按需导出,和vue.use全局注册,依赖于框架的拓展。 组件库的开发依赖框架的版本和node的版本,这个是需要说明的,然…

探索人工智能领域——每日20个名词详解【day6】

目录 前言 正文 总结 🌈嗨!我是Filotimo__🌈。很高兴与大家相识,希望我的博客能对你有所帮助。 💡本文由Filotimo__✍️原创,首发于CSDN📚。 📣如需转载,请事先与我联系以…

CloudCompare简单开发

一、概述 CloudCompare如何进行二次开发?_cloudcompare 二次开发-CSDN博客 开发一个功能,在原始CC的基础上添加一个拓展功能,如下: 二、功能开发 1、修改MainWindow.UI 重点是:要编译,不然在mainwindow.…

【从零开始学习Redis | 第六篇】爆改Setnx实现分布式锁

前言: 在Java后端业务中, 如果我们开启了均衡负载模式,也就是多台服务器处理前端的请求,就会产生一个问题:多台服务器就会有多个JVM,多个JVM就会导致服务器集群下的并发问题。我们在这里提出的解决思路是把…

Docker-简介、基本操作

目录 Docker理解 1、Docker本质 2、Docker与虚拟机的区别 3、Docker和JVM虚拟化的区别 4、容器、镜像的理解 5、Docker架构 Docker客户端 Docker服务器 Docker镜像 Docker容器 镜像仓库 Docker基本操作 1、Docker镜像仓库 镜像仓库分类 镜像仓库命令 docker lo…

Selenium 连接到现有的 Google Chrome 示例

python 3.7 selenium 3.14.1 urllib3 1.26.8 Google Chrome 119.0.6045.160 (64位) chromedriver.exe 119.0.6045.105(win32) 1 Google Chrome 添加参数 "--remote-debugging-port9222" 2 测试效果(chromedriver.exe 要和 Google Chrome 版本…

01、Tensorflow实现二元手写数字识别

01、Tensorflow实现二元手写数字识别(二分类问题) 01、Tensorflow实现二元手写数字识别(二分类问题) 02、Tensorflow实现手写数字识别(数字0-9) 开始学习机器学习啦,已经把吴恩达的课全部刷完了…

使用Redis构建简易社交网站(1)-创建用户与动态界面

目的 本文目的:实现简易社交网站中创建新用户和创建新动态功能。(完整代码附在文章末尾) 相关知识 本文将教会你掌握:1.redis基本命令,2.python基本命令。 redis基本命令 hget:从哈希中获取指定域的值…

java后端技术演变杂谈(未完结)

1.0版本javaWeb:原始servletjspjsbc 早期的jsp:htmljava,页面先在后端被解析,里面的java代码动态渲染完成后,成为纯html,再通过服务器发送给浏览器显示。 缺点: 服务器压力很大,因为…

python提取通话记录中的时间信息

您需要安装适合中文的SpaCy模型。您可以通过运行 pip install spacypython -m spacy download zh_core_web_sm来安装和下载所需的模型。 import spacy# 加载中文模型 nlp spacy.load(zh_core_web_sm)# 示例电话记录文本 text """ Agent: 今天我们解决一下这…

QT之QString

QT之QString 添加容器 点击栅格布局 添加容器,进行栅格布局 布局总结:每一个模块放在一个Group中,排放完之后,进行栅格布局。多个Group进行并排时,先将各个模块进行栅格布局,然后都选中进行垂直布…

华清远见嵌入式学习——C++——作业3

作业要求&#xff1a; 代码&#xff1a; #include <iostream>using namespace std;class Per { private:string name;int age;double *high;double *weight; public://有参构造函数Per(string n,int a,double h,double w):name(n),age(a),high(new double(h)),weight(ne…

14 网关实战:网关聚合API文档

上节课介绍了网关层的认证鉴权,今天这节介绍一下网关层如何聚合API接口文文档。 为什么需要聚合API接口文档? 大型微服务系统模块众多,木谷博客系统就有9个,如果这些服务的接口地址没有一个统一,那么客户端将要保存每个服务的接口地址,这个肯定是不现实。 先来看一下A…

11. 哈希冲突

上一节提到&#xff0c;通常情况下哈希函数的输入空间远大于输出空间&#xff0c;因此理论上哈希冲突是不可避免的。比如&#xff0c;输入空间为全体整数&#xff0c;输出空间为数组容量大小&#xff0c;则必然有多个整数映射至同一桶索引。 哈希冲突会导致查询结果错误&#…

机器学习的复习笔记3-回归的细谈

一、回归的细分 机器学习中的回归问题是一种用于预测连续型输出变量的任务。回归问题的类型和特点如下&#xff1a; 线性回归&#xff08;Linear Regression&#xff09;&#xff1a;线性回归是回归问题中最简单的一种方法。它假设自变量与因变量之间存在线性关系&#xff0c…

【Unity动画】状态机添加参数控制动画切换(Animator Controller)

Unity - 手册&#xff1a;动画参数 在Unity中&#xff0c;动画状态的切换是通过Animator Controller中的过渡&#xff08;Transition&#xff09;来实现的。过渡是状态之间的连接&#xff0c;控制过渡一般都是靠调用代码参数 我们来实现一个案例&#xff1a; 创建动画状态机&a…

vscode中使用luaide-lite插件断点调试cocos2dx-lua

使用quick-cocos2dx-lua&#xff0c;用了众多插件&#xff0c;包括免费的BabeLua,VS调试太慢&#xff0c;vscode上的免费的EmmyLua, 还有收费的luaide&#xff0c;都没搞出来&#xff0c;唯独这个免费luaide-lite用成功了&#xff0c;步骤也简单&#xff0c;可以断点调试&#…

数据结构第六课 -----链式二叉树的实现

作者前言 &#x1f382; ✨✨✨✨✨✨&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f382; ​&#x1f382; 作者介绍&#xff1a; &#x1f382;&#x1f382; &#x1f382; &#x1f389;&#x1f389;&#x1f389…

Java SpringBoot Controller常见写法

文章目录 环境Controller调用脚本运行结果总结 环境 系统: windows 11 工具: java, idea, git bash Controller 接口常见有以下几种方式 其中&#xff1a; Tobj 调用脚本 我的是windows 系统&#xff0c;使用 git bash 窗口运行, 用 cmd 或者 power shell 会有问题 curl …

C盘分析文件大小的软件

https://sourceforge.net/projects/windirstat/ 上面是windirstat的下载链接 界面是这样的&#xff1a; 选择C盘或者D盘&#xff0c;点击OK&#xff0c;就可以分析了 然后就可以看到哪些占比最高&#xff0c;可以针对性的清理