队列的基本操作及应用

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

循环队列的基本运算
(5)元素出队:
procedure delqueue(var Q:queue;var X:elemtype); begin if qempty(Q) then writeln(‘Underflow’) else begin Q.front:=(Q.front+1) mod maxsize; X:=Q.data[Q.front]; end; end;
最后根据队列sq中的存储信息和指针位 置,即可链接成从迷宫入口到出口的最短路 径。就上例而言,sq队列的最后情况为:
当rear指针指示的数据元素已到达出口 (6,8)时,根据rear所据元素的前趋序号 即可获得所要的走迷宫的最短路径(回溯)。
例题4:产生数(2002年NOIP普及组第3题) 给出一个整数n(n<2000)和k个变换规则(k≤15) 规则:① 1个数字可以变换成另1个数字; ② 规则中,右边的数字不能为零。 例如:n=234,k=2规则为 2 → 5 3 → 6 上面的整数234经过变换后可能产生出的整数为 (包括原数) 234 534 264 564 共4种不同的产生数 求经过任意次的变换(0次或多次),能产生出多 少个不同的整数。 仅要求输出不同整数个数。
(2)队列可以理解为一个数组,数组元素是如下记录: RECORD C10,C7,C3, pre: integer; END; 数组下标为容器状态号。下面是倒油过程的队列:
当倒油产生出第19个容器状态时已达到了题解的 目的。这时只要根据pre中的状态号17可以回溯到第 17个容器状态的pre值为15,依次可再获得13,11, 9,7,5,2,1容器状态号,从而即可得到本题的倒 油过程(共倒9次),而且是最少的倒油次数。
(1)从一个容器的状态(三个容器中油的 容量)看,虽然有可能经过上述六种倒油的 方法产生六种容器状态,但实际上这六种新 产生的容器状态,许多是已经出现过的状态。 例如初始状态(10,0,0)表示 C10=10, C7=0,C3=0,经过上述六种倒油方法只能产 生出两种新的容器状态(3,7,0),表示C10 向C7倒油的结果和(7,0,3),表示C10向C3 倒油的结果。如果再增加应该表示新容器状 态是由什么状态产生的指示pre,那么用这 三个容器倒油的过程就可以用队列的方法来 实现了。
图中的(1,1)→(2,2)→(3,3) →(3,4)→(4,5)→(4,6)→(5, 7)→(6,8)便是所求的一个这种路径。 【算法分析】 为了设计求走迷宫的路径,首先要对 宫进行描述,一种很 迷 自然的想法是把迷宫 变为0,1值的二维数 组,对上例而言可化 为:
探索路径的选择可描述为:
这样一来,迷宫中每个位置可探索的情况 就分为: * 只有三个探索方向的位置:如(1,1); * 有五个探索方向的位置:如(3,1); * 有八个探索方向的位置:如(3,2);
队列的基本运算
(3)判队满:若队列满,则返回值true, 否则返回值false: function qfull(Q:queue):Boolean; begin Qfull:=(Q.rear=maxsize-1); end;
队列的基本运算
(4)元素进队:若队列Q不满时,把元素X插入 到队列Q的队尾,否则返回信息“Overflow”:
⑤ 从列表中可以看出出口关卡号(17)的 被访问路径最短的是:
(17)←(16)←(19)←(18)←(1) ←开始
⑥ 根据题意,要求从存储数据中写出从入 口到出口的最少关卡路径的算法是: 从队列的最后一个关卡号开始,依次回访 它的前驱顶点,所得到的路径即为最短路 径。
算法如下:
i:=1;
while no[i]<>17 do i:=i+1 repeat write(‘(’,no[i], ‘)’); write(‘<- ’); i:=pre[i]; until i=0;
循环队列的基本运算
(2)判队列空: function qempty(Q:queue):Boolean; begin qempty:=(Q.front=Q.rear) end;
循环队列的基本运算
(3)判队满: function qfull(Q:queue):Boolean; begin qfull:=((Q.rear+1) mod maxsize=Q.front); end;
注意,从一个容器中向另一个容器中倒油,人 操作是很直观的,对编程来说则必须考虑: 1) 有没有油可倒? 2) 究竟倒多少?可能要全部倒入另一容器, 也可能只要倒一部分另一容器已经满了。
例题3:迷宫问题 右图是一个简单的 迷宫,迷宫图中阴影部 分是不通的路径,处于 迷宫中的每个位置都可 以向8个方向探索着按 可行路径前进。迷宫图 中阴影部分是不通的路径,处于迷宫中的每个 位置都可以向8个方向探索着按可行路径前进。 假设出口位置在最右下角(6,8),入口在最 左上角(1,1),试问能否设计出寻找一个从 入口到出口的最短路径的算法呢?
例题2:有10升油在10升的容器中,另 有两个7升和3升的空容器,现要求用 这三个容器倒油,使得最后在10升和7 升的容器中各有5升油。
提示:三个容器可以看作三个变量 C10,C7,C3,每次倒油的可能性只有 如下六种情况: ① C10向C7倒油 ② C10向C3倒油 ③ C7向C10倒油 ④ C7向C3倒油 ⑤ C3向C10倒油 ⑥ C3向C7倒油
队列的应用
解决主机与外部设备之间速度不匹配的 问题(如:主机与打印机,设置一个打 印数据缓冲区); 解决由多用户引起的资源竞争问题(如: CPU资源的竞争,操作系统按照每个请求 的先后顺序,排成一个队列)。

典型例题
例题1:1995年高中组基础题第4 题,从 入口(1)到出口(17)的可行路线图中, 数字标号表示关卡:
procedure inqueue(var Q:queue;X:elemtype); begin if qfull(Q) then writeln(‘Overflow’) else begin Q.rear:=Q.rear+1; Q.data[Q.rear]:=X; end end;
队列的基本运算
例如:从(1,1)入口进入到达(3, 3),往下探索时队列sq的情况:
注意,前趋采用了仅登记前趋在队列中的序 号(前趋是由front指针指示的数据元素); 为了防止被探索过的踪迹被重复探索,被探 索到的可通行路径需在迷宫中做上标记,这里采 用在迷宫数据中将0换成-1的方法实现,这样在走 出迷宫时可以再 把迷宫数据还原 为原来的样子。 例如上例,探索 到位置(3,3) 的迷宫数据为:
循环队列

所谓循环队列,就 是将队列存储空间 的最后一个位置绕 到第一个位置,形 成逻辑上的环状空 间,供队列循环使 用,循环队列的定 义如队列。
循环队列的基本运算
(1)初始化: procedure iniqueue(var Q:queue); begin Q.front:=0; Q.rear:=0; end;
③ 由于本题是一个典型的图的遍历问题, 此题采用的是图的广度优先遍历算法,并 利用队列的方式存储顶点之间的联系。即 访问一个点,将其后继结点入队,并存储 它的 前趋结点所在单元下标 ,直到最后从 (17)点出口; ④ 从最后出口的关卡号(17)开始回访 它的前趋卡号,则回返的搜索路径便是最 短路径(跳过许多不必要搜索的关卡);
现将上面的路线图,按记录结构存储如下 :
请设计一种能从存储数据中求出从入口到 出口经过最少关卡路径的算法。
【问题分析与答案】 ① 该题是一个路径搜索问题,根据图示,从 入口(1)到出口(17)可以有多种途径,其 中最短的路径只有一条,那么如何找最短路 径是问题的关键; ② 根据题意,用一维数组存储各关卡号 (设NO),用另一个数组存储访问到某关卡 号的前趋卡号所在数组单元下标(设PRE);
循环队列的基本运算
(4)元素进队:
procedure inqueue(var Q:queue;X:elemtype); begin if qfull(Q) then writeln(‘Overflow’) else begin Q.rear:=(Q.rear+1) mod maxsize; Q.data[Q.rear]:=X; end end;
队列的存储结构
2.链式存储 链式存储的队列称为链队
队列的基本运算
(1)初始化:设定Q为一空队列: procedure iniqueue(var Q:queue); begin Q.front:=-1; Q.rear:=-1; end;
队列的基本运算
(2)判队列空:若队列Q为空,则返回值 true,否则返回值false: function qempty(Q:queue):Boolean; begin qempty:=(Q.front=Q.rear) end;
(5)元素出队:若队列Q不空,则把队头元素删 除并返回值给X,否则输出信息“Underflow”:
procedure delqueue(var Q:queue;var X:elemtype); begin if qempty(Q) then writeln(‘Underflow’) else begin Q.front:=Q.front+1; X:=Q.data[Q.front]; end; end;

基本术语
队空:当队列中没有元素时称为空队列; 队满:当队列中单元全部被占用; 进队:向队列中插入新元素; 出队:从队列中删除元素; (假)溢出:队尾指针指向最后一个位 置,但队头前面仍有空闲的单元可被利 用。

队列操作示意图
front=rear=-1
front=-1 rear=2
队列的基本操作及应用
2005.1
南京
队列的定义
队列(queue)简称队,是一种运算受限 的线性表,其限制是仅允许在表的一端 进行插入,而在表的另一端进行删除。 我们把进行插入的一端称作队尾 (rear),进行删除的一端称作队头 (front)。 队列也称作先进先出表(First In First Out,简称FIFO表)。
能否不分情况统一按八种情况探索前 进的路径呢?只要把原始迷宫数据修正如 下即可达到目的(外加Байду номын сангаас圈不通的围墙);
Mg:array[0..m+1,0..n+1] of integer;
探索方向可用x,y的增量组成数组:
Zl:array[1..8,1..2] of –1..1
第二个要解决的问题应当考虑探索前进路 径时如何把探索的踪迹记录下来,记录的踪迹 一般应包括来处和当前位置,现设计如下顺序 队列来完成探索路径的踪迹: type sqtype=array[1..r] of record x,y:integer; {当前坐标} pre:0..r; {前趋位置} end; {这里的r一般<=m×n,即迷宫的最大空位数目} var sq:sqtype;
队列的基本运算
(6)取队头元素:若队列不空,返回队头 元素的值,否则返回信息“Underflow”: function gethead(Q:queue):elemtype; begin if qempty(Q) then writeln(‘Underflow’) else gethead:=Q.data[Q.front+1]; end;
循环队列的基本运算
(6)取队头元素:
function gethead(Q:queue):elemtype; begin if qempty(Q) then writeln(‘Underflow’) else gethead:=Q.data[(Q.front+1) mod maxsize]; end;
front=5 rear=8 front=5 rear=9
(a) 空队
(b)有3个元素
(c)一般情况
(d) 假溢出现象
队列的存储结构
1.顺序存储 顺序存储的队称为顺序队列 type queue=record data:array[0..maxsize-1] of elemtype front, rear : integer ; end; front指向队列中第一个元素的前一个单元; rear指向队列中最后一个元素单元。
相关文档
最新文档