数据结构 队列
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
12
5.3用链表仿真队列 5.3用链表仿真队列
除了使用数组结构外,也可以使用链表结构来建立队列。 队列的链表结构如下:
struct node { char data; node *next; }; struct queue { node *front,*rear; };
其中front和rear是作为队列前后端的输出、输入指针的控 制,由于刚刚建立的队列为空,故先将front和rear指向 NULL。
31
5.5 双向队列 .
前面所提到的队列为单向队列,即从队列后端进行输入、前端进 行输出。顾名思义,双向队列即可从前后端进行队列数据的输出 及输入,如下图所示: 这样的结构最常用于计算机的CPU调度。所谓“CPU调度”是在多 人使用一个CPU的情况下,由于CPU在同一时间只能执行一项工作, 故将每个人欲处理的工作先存于队列中,待CPU闲置时再从队列中 取出一项待执行的工作进行处理。而在双向队列两端均可输出、 输入的结构下,正好符合在CPU调度处理上的不同请求。 双向队列的设计有很多种,在此我们根据输出、输入方向的限制, 将其分为两种: 1.输入限制性双向队列 2.输出限制性双向队列
32
5.5.1 输入限制性双向队列
“输入限制性双向队列”是限制只能在队列的 一端(后端)进行输入,而数据的输出则可在队 列的两端(前后端)操作。 程序实例:已知一队列,欲使用“输入限制性 双向队列”方式进行数据输出。 程序源代码:
33
#include <iostream.h> #include <stdlib.h> #define MaxSize 10 int queue [MaxSize] ; int front = -1; int rear = -1; void addqueue (int value) { rear= (rear+1) % MaxSize; if (front==rear) cout<<"The queue is full! !"; else queue[rear] = value; } int rear_delqueue () { int temp; if (front == rear) return -1; temp=queue[rear]; rear--; if (rear<0 && front!=-1) rear=MaxSize-1; return temp; }
26
当 我 们 将 数 据 存 入 队 列 时 称 为 “ addqueue” , addqueue的处理主要有两个步骤: (1)将队尾指针往前移:rear+1; (2)若尾指针rear小于等于队列的最大索引值MaxSize1,则将数据存入rear所指的数组元素中,否则无法 存入数据。
27
环状队列入队addqueue函数
16
入队addqueue函数
void addqueue(queue &q,char x) { node *New; New=(node *)new(node); New->data =x; New->next =NULL; if(q.rear ==NULL) q.front =q.rear =New; else { q.rear ->next =New; q.rear =New; } }
19
显示队列print函数
void print(queue q) { node *p; p=q.front ; while(p!=NULL) { cout<<setw(4)<<p->data ; p=p->next ; } cout<<endl; }
20
5.4环状队列 5.4环状队列
我们在5.2节中提到,当队尾指针rear等于MaxSize-1 时,不论队列是否有空间,都无法再将数据存于队列 中。 如果要将数据往队列前端移动以挪出空间,需要花费 很多时间。为解决这样的问题,我们使用环状队列, 控制队列前尾指针front、rear来充分运用队列中的 空间。 环状队列的概念如下图: 图略(P126)
29
环状队列出对队delqueue函数
void delqueue(queue &q,char &x) { q.front=(q.front +1)%maxsize; x=q.data [q.front ]; }
30
Biblioteka Baidu
显示环状队列数据print函数
void print(queue q) { int i; if (q.front <q.rear ) for(i=q.front +1;i<=q.rear ;i++) cout<<setw(4)<<q.data [i]; else { for(i=q.front+1 ;i<maxsize;i++) cout<<setw(4)<<q.data [i]; for(i=0;i<=q.rear ;i++) cout<<setw(4)<<q.data [i]; } cout<<endl; }
10
出队delqueue函数
void delqueue(queue &q,char &x) { q.front ++; x=q.data [q.front ]; }
11
显示队列数据print函数
void print(queue q) { int i; for(i=q.front +1;i<=q.rear ;i++) cout<<setw(4)<<q.data [i]; cout<<endl; }
2
抽象数据类型Queue
元素:无限制,由应用决定 结构:保持元素先进先出的特性。 操作: (1)void Init(Queue &Q)//初始化生成一个空栈 (2)void Addqueue(Element e,Queue &Q)/入队操作 (3)void Delqueue(Elment &e,Queue &Q)//出队操作 (4)Element Top(Queue Q)//读队首元素值 (5)bool Empty(Queue Q)//判队列空操作 (6)bool Full(Queue Q)//判队列满操作
3
5.2用数组仿真队列 用数组仿真队列
队列本身是有序列表,若使用数组的结构来存储队 列的结构,则队列结构数组的声明如下: struct queue { int queue[MaxSize]; int front; int rear; }
其中MaxSize是该队列的最大容量。因为队列的输出、 输入分别从前后端来处理,因此需要两个变量front和 rear分别记录队列前后端的索引值,front会随着数据输 出而变动,而rear则是随着数据输入而改变。
34
int front_delqueue () { if (front == rear) return -1; front++ ; if (front == MaxSize) front =0; return queue [front] ; } void main ( ) { int select; int output_queue [5] ; int input_queue[5]={5,4,3,2,1}; int temp,Position=0,i; for (i=0;i<5;i++) addqueue (input_queue[i]); cout<<"The original queue order :"; for (i=0;i<5;i++) cout<< input_queue[i]; cout<<endl;
23
初始化环状队列
void init(queue &q) { q.front=0; q.rear=0; }
24
判断环状队列空empty函数
bool empty(queue q) { return(q.front==q.rear); }
25
判断环状队列满full函数
bool full(queue q) { return ((q.rear+1)%maxsize==q.front ); }
17
数据输出是从队列的前端front处理,其步骤如下: 步骤1:先保留对头指针front所指的位置 步骤2:将头指针front指向下一个节点 步骤3:取出之前保留头指针所指的节点内容 步骤4:释放原队列前端所指的节点内容
18
出队delqueue函数
void delqueue(queue &q,char &x) { node *p; p=q.front ; q.front =q.front ->next ; x=p->data ; delete p; }
4
初始化队列
void init(queue &q) { q.front=-1; q.rear=-1; }
5
判断队列空empty函数
bool empty(queue q) { return(q.front==q.rear); }
6
判断队列满full函数
bool full(queue q) { return (q.rear ==maxsize-1); }
第五章 队列
5.1 何谓队列 队列数据结构规定:在有序列表中数据的输出、 输入是分别由不同端进行处理,输出端称为前 端(front),输入端称为后端(rear),这样会使得 先存入的数据会先被取出,也就是具有先进先 出FIFO的特性。
1
队列的应用也很多,下面列出几个较常见的: 1.图形的广度优先搜索法。 2.优先队列,此种队列在取出元素时是根据所存元素的 某项特性值或优先权而取出具最小或最大数值的元素。 3.操作系统中的工作调度,若工作的优先权相同,则采 用先到先做的原则。 4.用于“spooling” (假脱机,信息暂存,当信息需进一步 处理时,对其进行暂时存贮),先将输出数据写在磁 盘上,再由打印机把先存入者先处理的顺序将数据输 出。 队列和堆栈一样也可使用两种结构:数组结构和链表 结构。
7
当 我 们 将 数 据 存 入 队 列 时 称 为 “ addqueue” , addqueue的处理主要有两个步骤: (1)将队尾指针往前移:rear+1; (2)若尾指针rear小于等于队列的最大索引值MaxSize1,则将数据存入rear所指的数组元素中,否则无法 存入数据。
8
入队addqueue函数
13
初始化队列
void init(queue &q) { q.front =q.rear =NULL; }
14
判断队列空empty函数
bool empty(queue q) { return q.front==NULL ; }
15
队列数据的输入是从后端rear进行,其步骤如下: 步骤1:将rear指针所指位置的next指针指向新节点 步骤2:将rear指针移动到新节点之上。
21
当插入数据时,尾指针rear会往箭头方向前进,而 输出数据时,头指针front也会往箭头方向前进,可 看出队列空间的利用是按照逆时针方向循环,直到 rear往前移动到等于front时,表示队列己满,无法 输入数据。 从上图看来,虽然环状队列看似一个封闭的圆环, 但事实上环状队列仍然是一个线性数组,和一般队 列比较起来,主要是前后端使用技巧的差异。在此 需特别注意的是,环状队列中的头指针所指的数组 位置并没有内容值存在,输出的值为front的下一个 元素,故环状队列实际上所能使用的空间为 MaxSize-1。
void addqueue(queue &q,char x) { q.rear ++; q.data [q.rear ]=x; }
9
从队列中取出数据项称为“delqueue” ,delqueue的 操作可分为4个步骤: (1)检查队列中是否有数据存在。 (2)若头指针front等于尾指针rear,则表示队列中无数 据。 (3)若头指针front不等于尾指针rear,则将队列头指针 往前移front+1。 (4)取出队头指针所指的数组元素内容。
22
当尾指针rear等于MaxSize-1时需回到队列的最前端, 故当输入数据时,rear所指的数组元素索引值采 用下列的计算方法: (rear+1)mod MaxSize 若尾指针rear不断前进直到等于头指针front时,那 么表示队列己满,但如果队列为空时rear也等于 front,为区分这两种状况,必须使用不同的条件 来加以判断。 当队列为满:(rear+1)mod MaxSize=front 当队列空:front=rear 这两个条件所代表的意义是不一样的。
void addqueue(queue &q,char x) { q.rear=(q.rear +1)%maxsize; q.data [q.rear ]=x; }
28
从队列中取出数据项称为“delqueue” ,delqueue的 操作可分为4个步骤: (1)检查队列中是否有数据存在。 (2)若头指针front等于尾指针rear,则表示队列中无数 据。 (3)若头指针front不等于尾指针rear,则将队列头指针 往前移front+1。 (4)取出队头指针所指的数组元素内容。