第四篇 数据结构-队列和串

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

§9.3 队列

队列是不同于栈的另一种线性表。在日常生活中,无论是购物、订票或候车都有可

能要排队。排队所遵循的原则是“先来先服务”,后来者总是加到队尾,排头者总是

先离开队伍。队列就是从日常生活中的排队现象抽象出来的。

一、队列的定义

所谓队列,就是允许在一端进行插入,在另一端进行删除的线性表。允许插入的

一端称为队尾,通常用一个队尾指针r指向队尾元素,即r总是指向最后被插入的元

素;允许删除的一端称为队首,通常也用一个队首指针f指向排头元素的前面。初始

时f=r=0(如下图)。

显然,在队列这种数据结构中,最先插入在元素将是最先被删除;反之最后插入

的元素将最后被删除,因此队列又称为“先进先出”(FIFO—first in first out)

的线性表。与栈相似,队列的顺序存储空间可以用一维数组q[1‥m]模拟:

我们按照如下方式定义队列:

Const

m=队列元素的上限;

Type

equeue=array[1…m] of qtype; {队

列的类型定义}

Var

q:equeue;

{队列}

r,f:integer; {队尾指针

和队首指针}

二、队列的基本运算

队列的运算主要有两种:入队(aDD)和出队(DEL)

1、过程ADD(q,x,r)—在队列q的尾端插入元素x

procedure ADD(var q: equeue; x:qtype; var r:integer);

begin

if r=m then writeln (’overflow’) {上溢}

else begin {后移队尾指针并

插入元素x}

r←r+1; q[r]←x;

end;{else}

end;{ADD}

2、过程DEL(q,y,f,r)—取出q队列的队首元素y

procedure DEL(var q:equeue; var y:qtype; var f:integer);

begin

if f=r then writeln (’under flow’) {下溢}

else begin {后移队首指针并取

出队首元素}

f←f+1; y←q[f];

end;{else}

end;{DEL}

由于队列只能在一端插入,在另一端删除,因此随着入队及出队运算的不断进行,

就会出现一种有别于栈的情形:队列在数组中不断地向队尾方向移动,而在队首的前

面产生一片不能利用的空闲存储区,最后会导致当尾指针指向数组最后一个位置(即

r=m)而不能再加入元素时,存储空间的前部却有一片存储区无端浪费,这种现象称为

“假溢出”。下图给出了一个“假溢出”的示例:

三、循环队列

为了解决“假溢出”的问题,我们不妨作这样的设想:在队列中,当存储空间的

最后一个位置已被使用而要进行入队运算时,只要存储空间第一个位置空闲,便可将

元素加入到第一个位置,即将存储空间的第一个位置作为队尾。采用首尾相接的队列

结构后,可以有效地解决假溢出的问题,避免数据元素的移动,这就是所谓的循环队

列。下图给出了循环队列的结构。

循环队列将队列存储空间的最后一个位置绕到第一个位置,形成逻辑上的环状空

间,供队列循环使用,循环队列的存取方法亦为““先进先出””。

对循环队列操作有以下几种状态:

1.⑴初始时队列空,队首指针和队尾指针均指向存储空间的最后一个位置,即

f=r=m。

2.⑵入队运算时,尾指针进一,即

r←r+1; if r=m+1 then r←1;

这两条语句可用一条语句替代:

r←r mod m+1;

3.⑶出队运算时,首指针进一,即

f←f+1;if f=m+1 then f←1;

这两条语句可用一条语句替代:

f←f mod m+1;

4.⑷队列空时有f=r。

5.⑸队列满时有f=r mod m+1。(为了区分队列空和队列满,改用“队尾指针追上队

首指针”这一特征作为队列满标志。这种处理方法的缺点是浪费队列空间的一个存储单元)

循环队列的运算有两种:

1、过程ADD2(q,x,r)—在循环队列q中插入一个新元素x

procedure ADD2 (var q:equeue; x:qtype; var r:integer);

begin

t←r mod m+1;

{计算插入位置}

if t=f then writeln(’full’) {队列满}

else begin {新元素

x插入队尾}

r←t; q[r]←x;

end;{else}

end;{ADD2}

2、过程DEL2(q,y,f)—从循环队列q中取出队首元素y

procedure DEL2 (var q:equeue; var y:qtype; var f:inteqer);

begin

if f=r then writeln (’empty’) {队列空}

else begin

f←f mod m+1;y←q[f]; {取

出队首元素}

end;{else}

end;{DEL2}

队列的应用范围很广,其中最为典型的应用是广义表的计算和图的宽度优先搜

索。本章节着重讲解前者,至于后者,放到“§10.2 图”中详述。

四、队列的应用——计算广义线性表

相关文档
最新文档