目录
队列的概述
- 队列是一种重要的线性结构,同栈一样,属于一种操作受限的线性表
- 队列(queue),只允许在表的一端进行插入操作,而在另一端进行删除操作
- 队列允许插入的一端叫做队尾(rear),允许删除的一端叫做队头(front)
- 队列元素遵循先进先出,即最先进入队列的元素最先出队列
队列的顺序存储结构
- 开辟一组地址连续的存储单元依次存放从队列头到队尾的元素
- 设有两个指针(front和rear),当front = rear 时表示队列为空
- 队列插入新的元素时,队尾指针(rear)增1,始终指向队列尾元素的下一位置(非空队列)
- 队列删除元素时,队头指针(front)增1,始终指向队列的头元素(非空队列)
顺序队列在不断进行插入、删除操作后,会导致队头(front)和队尾(rear)指针的不断增加,最终导致队列中虽然仍有空间进行元素的插入,但无法执行该操作(空间的假溢出)
当出现假溢出的情况时,使用循环队列解决假溢出的情况,让队尾指针直接指向开辟空间的第一块区域,即如下图所示
使用循环队列的方法,可以将其想象成开辟了一个环形连续空间(并不存在环形空间,实际仍是线形的连续空间)
循环队列解决了假溢出的问题,但新的问题又出现了,此时 front = rear 既可以表示队列已满,又可以表示队列为空
两种解决方式: 其一是另设一个标识位以区别队列是空还是满,其二是少用一个元素空间,规定以队列头指针在队列尾指针的下一位置上,作为满队列状态,即如图所示
部分算法分析
- 循环队列的定义
typedef struct {
//初始化的动态分配存储空间
QElemType* base;
//头指针,若队列不为空,指向队列头元素
int front;
//尾指针,若队列不为空,指向队列尾元素的下一个位置
int rear;
}LoopQueue;
队头指针(front)以及队尾指针(rear)类型设置为 int类 型,因为开辟的空间是连续型的一块空间,相当于数组,所以只需要对这块空间的索引进行相关操作即可
- 元素入队列操作
//从队尾插入元素至队列中(入队列)
Status InsertLoopQueue(LoopQueue& Q, QElemType data) {
//判断队列是否已满
if ((Q.rear + 1) % MAX_QSIZE == Q.front) {
cout << "循环队列已满,入队列操作失败" << endl;
return ERROR;
}
Q.base[Q.rear] = data;
Q.rear = (Q.rear + 1) % MAX_QSIZE;
return OK;
}
队尾指针(rear)始终指向队列最后插入的元素的后一个位置,之后让队尾指针增1,当rear的值为队列最大存储容量值 - 1时(即 MAX_QSIZE - 1 ),再进行入队列操作时会出现假溢出现象
让队尾指针增1后再对队列最大存储容量值取模(即(Q.rear + 1) % MAX_QSIZE),rear的值重新从索引0开始
举个例子,如图
当元素a7入队列时,rear的值由7 + 1等于8,此时对队列最大容量值(MAX_QSIZE)取模,rear = 0,解决了假溢出的问题
循环队列的表示和实现
- global.h
- LoopQueue.h
- LoopQueueTest.cpp
global.h
相关头文件的引用,以及相应全局变量、常量的声明
#pragma once
#include<iostream>
#include<string.h>
#include<stdlib.h>
#include<stdio.h>
#include<windows.h>
using namespace std;
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define EQ(a,b) ((a) == (b))
#define LT(a,b) ((a) < (b))
#define LQ(a,b) ((a) <= (b))
#define MT(a,b) ((a) > (b))
#define MQ(a,b) ((a) >= (b))
typedef int Status;
LoopQueue.h
循环队列的定义以及循环队列的相关操作算法的实现
#pragma once
#include"global.h"
#define QElemType int
#define MAX_QSIZE 100
typedef struct {
//初始化的动态分配存储空间
QElemType* base;
//头指针,若队列不为空,指向队列头元素
int front;
//尾指针,若队列不为空,指向队列尾元素的下一个位置
int rear;
}LoopQueue;
//循环队列的初始化(构造一个空队列)
Status InitLoopQueue(LoopQueue& Q) {
Q.base = (QElemType*)malloc(MAX_QSIZE * sizeof(QElemType));
//判断空间分配是否成功
if (!Q.base)
return ERROR;
//将头指针与尾指针相等
Q.front = Q.rear = 0;
return OK;
}
//返回循环队列中已有元素的个数
int QueueLength(LoopQueue Q) {
return (Q.rear - Q.front + MAX_QSIZE) % MAX_QSIZE;
}
//从队尾插入元素至队列中(入队列)
Status InsertLoopQueue(LoopQueue& Q, QElemType data) {
//判断队列是否已满
if ((Q.rear + 1) % MAX_QSIZE == Q.front) {
cout << "循环队列已满,入队列操作失败" << endl;
return ERROR;
}
Q.base[Q.rear] = data;
Q.rear = (Q.rear + 1) % MAX_QSIZE;
return OK;
}
//将队列的头元素删除(出队列)
Status DeleteLoopQueue(LoopQueue& Q, QElemType& data) {
//判断队列是否尾空
if (Q.front == Q.rear) {
cout << "该队列为空队列,出队列操作失败" << endl;
return ERROR;
}
data = Q.base[Q.front];
Q.front = (Q.front + 1) % MAX_QSIZE;
return OK;
}
//循环队列的赋值操作初始化
void InitLoopQueueData(LoopQueue& Q) {
cout << "循环队列赋值初始化(赋值不超过" << MAX_QSIZE - 1 << "个元素)" << endl;
cout << "输入插入循环队列元素的个数:" << endl;
int nums = 0;
cin >> nums;
cout << "请输入" << nums << "个元素:" << endl;
QElemType data = 0;
for (int i = 0; i < nums; i++) {
cin >> data;
Q.base[Q.rear] = data;
Q.rear = (Q.rear + 1) % MAX_QSIZE;
}
cout << "循环队列初始化成功" << endl;
}
//循环队列的遍历操作
void ShowLoopQueue(LoopQueue Q) {
cout << "队列中的元素有:" << endl;
while (Q.front != Q.rear) {
cout << Q.base[Q.front] << " ";
Q.front = (Q.front + 1) % MAX_QSIZE;
}
cout << endl;
}
LoopQueueTest.cpp
#include"LoopQueue.h"
int main() {
LoopQueue queue;
InitLoopQueue(queue);
InitLoopQueueData(queue);
ShowLoopQueue(queue);
int length = QueueLength(queue);
cout << "循环队列中的元素个数有:" << length << endl;
cout << "---入队列操作---,输入数据:" << endl;
QElemType data;
cin >> data;
InsertLoopQueue(queue, data);
ShowLoopQueue(queue, data);
cout << "---出队列操作---" << endl;
DeleteLoopQueue(queue);
ShowLoopQueue(queue);
}
运行结果
循环队列赋值初始化(赋值不超过99个元素)
输入插入循环队列元素的个数:
7
请输入7个元素:
12 34 54 23 65 234 767
循环队列初始化成功
队列中的元素有:
12 34 54 23 65 234 767
循环队列中的元素个数有:7
---入队列操作---,输入数据:
345
队列中的元素有:
12 34 54 23 65 234 767 345
---出队列操作---
队列中的元素有:
34 54 23 65 234 767 345F:\DataStructureForC++\Project\Debug\Project1.exe (process 14648) exited with code 0.