目录
前言
队列也是一中受限的线性表,只能在表的一段进行插入操作,在表的另外一段进行删除操作
。和线性表一样,仍然是一对一的关系。存储结构也有两种方式:顺序队列和链队列。运算规则为先进先出。基本操作位入队或者出队,建空队列,判断队列为空或者队列已满等操作。
队列在现实中也有着很多的应用场景,例如离散事件的模拟、操作系统中的作业调度等。
队列仅在表尾进行插入操作,在表头进行删除操作。它是一种先进先出的线性表。
在队首删除元素成为出队,在队尾插入元素成为入队。
1.队列的顺序存储方式的实现
1.定义
#define MAXQSIZE 100 // 最大队列长度
struct SeqListQueue{
int *base;
int front;
int rear;
};
2.队列初始化
// 队列初始化
void initQueue(SeqListQueue &seqQueue){
seqQueue.base = (int *)malloc(sizeof(int) * MAXQSIZE); // 为队列的数组成员分配内存空间
if (!seqQueue.base) {
std::cerr << "内存分配失败!" << std::endl;
exit(EXIT_FAILURE);
}
seqQueue.front = seqQueue.rear = 0; // 初始化队列的 front 和 rear 指针
}
3.销毁
// 销毁队列
void destroyQueue(SeqListQueue &seqQueue) {
free(seqQueue.base);
seqQueue.base = nullptr;
seqQueue.front = seqQueue.rear = 0;
}
4.队列是否为空
// 判断队列是否为空
bool isEmptyQueue(SeqListQueue seqQueue) {
return seqQueue.front == seqQueue.rear;
}
5.队列长度
// 获取队列长度
int queueLength(SeqListQueue seqQueue) {
return (seqQueue.rear - seqQueue.front + MAXQSIZE) % MAXQSIZE;
}
6.清空队列
// 清空队列
void clearQueue(SeqListQueue &seqQueue) {
seqQueue.front = seqQueue.rear = 0; // 将 front 和 rear 指针重置为零
}
7.队列头元素
// 获取队列的队首元素
bool getFront(SeqListQueue seqQueue, int &element) {
if (seqQueue.front == seqQueue.rear) {
std::cerr << "队列为空,无法获取队首元素!" << std::endl;
return false;
}
element = seqQueue.base[seqQueue.front];
return true;
}
8.入队
// 入队
bool enQueue(SeqListQueue &seqQueue, int element) {
if ((seqQueue.rear + 1) % MAXQSIZE == seqQueue.front) {
std::cerr << "队列已满,无法入队!" << std::endl;
return false;
}
seqQueue.base[seqQueue.rear] = element;
seqQueue.rear = (seqQueue.rear + 1) % MAXQSIZE;
return true;
}
9.出队
// 出队
bool deQueue(SeqListQueue &seqQueue, int &element) {
if (seqQueue.front == seqQueue.rear) {
std::cerr << "队列为空,无法出队!" << std::endl;
return false;
}
element = seqQueue.base[seqQueue.front];
seqQueue.front = (seqQueue.front + 1) % MAXQSIZE;
return true;
}
10.完整代码
#include <iostream>
#include <cstdlib> // for malloc, free
#define MAXQSIZE 100 // 最大队列长度
struct SeqListQueue{
int *base;
int front;
int rear;
};
// 队列初始化
void initQueue(SeqListQueue &seqQueue){
seqQueue.base = (int *)malloc(sizeof(int) * MAXQSIZE); // 为队列的数组成员分配内存空间
if (!seqQueue.base) {
std::cerr << "内存分配失败!" << std::endl;
exit(EXIT_FAILURE);
}
seqQueue.front = seqQueue.rear = 0; // 初始化队列的 front 和 rear 指针
}
// 入队
bool enQueue(SeqListQueue &seqQueue, int element) {
if ((seqQueue.rear + 1) % MAXQSIZE == seqQueue.front) {
std::cerr << "队列已满,无法入队!" << std::endl;
return false;
}
seqQueue.base[seqQueue.rear] = element;
seqQueue.rear = (seqQueue.rear + 1) % MAXQSIZE;
return true;
}
// 出队
bool deQueue(SeqListQueue &seqQueue, int &element) {
if (seqQueue.front == seqQueue.rear) {
std::cerr << "队列为空,无法出队!" << std::endl;
return false;
}
element = seqQueue.base[seqQueue.front];
seqQueue.front = (seqQueue.front + 1) % MAXQSIZE;
return true;
}
// 输出队列元素
void printQueue(SeqListQueue seqQueue) {
int i = seqQueue.front;
while (i != seqQueue.rear) {
std::cout << seqQueue.base[i] << " ";
i = (i + 1) % MAXQSIZE;
}
std::cout << std::endl;
}
// 销毁队列
void destroyQueue(SeqListQueue &seqQueue) {
free(seqQueue.base);
seqQueue.base = nullptr;
seqQueue.front = seqQueue.rear = 0;
}
// 判断队列是否为空
bool isEmptyQueue(SeqListQueue seqQueue) {
return seqQueue.front == seqQueue.rear;
}
// 获取队列长度
int queueLength(SeqListQueue seqQueue) {
return (seqQueue.rear - seqQueue.front + MAXQSIZE) % MAXQSIZE;
}
// 清空队列
void clearQueue(SeqListQueue &seqQueue) {
seqQueue.front = seqQueue.rear = 0; // 将 front 和 rear 指针重置为零
}
// 获取队列的队首元素
bool getFront(SeqListQueue seqQueue, int &element) {
if (seqQueue.front == seqQueue.rear) {
std::cerr << "队列为空,无法获取队首元素!" << std::endl;
return false;
}
element = seqQueue.base[seqQueue.front];
return true;
}
int main() {
SeqListQueue seqQueue;
initQueue(seqQueue); // 初始化队列
// 测试入队
for (int i = 1; i <= 5; ++i) {
enQueue(seqQueue, i * 10);
}
// 输出队列元素
std::cout << "队列元素:";
printQueue(seqQueue);
// 获取队首元素
int frontElement;
if (getFront(seqQueue, frontElement)) {
std::cout << "队首元素:" << frontElement << std::endl;
}
// 测试出队
int element;
for (int i = 0; i < 3; ++i) {
if (deQueue(seqQueue, element)) {
std::cout << "出队元素:" << element << std::endl;
}
}
// 输出队列元素
std::cout << "队列元素:";
printQueue(seqQueue);
// 判断队列是否为空
if (isEmptyQueue(seqQueue)) {
std::cout << "队列为空" << std::endl;
} else {
std::cout << "队列不为空" << std::endl;
}
// 获取队列长度
std::cout << "队列长度为:" << queueLength(seqQueue) << std::endl;
// 清空队列
clearQueue(seqQueue);
// 判断队列是否为空
if (isEmptyQueue(seqQueue)) {
std::cout << "清空队列后,队列为空" << std::endl;
} else {
std::cout << "清空队列后,队列不为空" << std::endl;
}
// 销毁队列
destroyQueue(seqQueue);
return 0;
}
2.队列的链式存储方式的实现
1.定义
typedef struct QNode {
int data; // 元素
struct QNode *next; // 指向下一个节点的指针
} QNode, *QueuePtr;
typedef struct {
QueuePtr front; // 队首指针
QueuePtr rear; // 队尾指针
} LinkQueue;
2.队列初始化
// 初始化队列
void initQueue(LinkQueue &link) {
link.front = link.rear = (QueuePtr)malloc(sizeof(QNode));
if (!link.front) {
exit(-1); // 内存分配失败
}
link.front->next = NULL;
}
3.销毁
void destroyQueue(LinkQueue &queue) {
QueuePtr p, q;
p = queue.front;
while (p) {
q = p->next;
free(p);
p = q;
}
queue.front = queue.rear = nullptr; // 将队首和队尾指针置为空指针
}
4.队列是否为空
// 判断队列是否为空
bool isEmptyQueue(LinkQueue queue) {
return queue.front == queue.rear;
}
5.队列长度
// 获取队列长度
int queueLength(LinkQueue queue) {
int length = 0;
QueuePtr p = queue.front->next;
while (p) {
length++;
p = p->next;
}
return length;
}
6.清空队列
// 清空队列
void clearQueue(LinkQueue &queue) {
QueuePtr p = queue.front->next;
while (p) {
QueuePtr temp = p;
p = p->next;
free(temp);
}
queue.front->next = nullptr;
queue.rear = queue.front;
}
7.队列头元素
// 获取队列的头元素
int getFront(LinkQueue queue) {
if (isEmptyQueue(queue)) {
cout << "队列为空!" << endl;
return -1;
}
return queue.front->next->data;
}
8.入队
// 入队
void enQueue(LinkQueue &queue, int element) {
QueuePtr p = (QueuePtr)malloc(sizeof(QNode)); // 申请内存空间
if (!p) {
exit(-1); // 内存分配失败
}
p->data = element;
p->next = NULL;
queue.rear->next = p;
queue.rear = p;
}
9.出队
// 出队
int deQueue(LinkQueue &queue, int &element) {
if (queue.rear == queue.front) {
return 0; // 队列为空
}
QueuePtr p = queue.front->next;
element = p->data;
queue.front->next = p->next;
if (queue.rear == p) {
queue.rear = queue.front;
}
free(p);
return 1;
}
10.完整代码
#include <iostream>
#include <cstdlib> // for malloc, free
using namespace std;
typedef int ElementType;
typedef struct QNode {
int data; // 元素
struct QNode *next; // 指向下一个节点的指针
} QNode, *QueuePtr;
typedef struct {
QueuePtr front; // 队首指针
QueuePtr rear; // 队尾指针
} LinkQueue;
// 初始化队列
void initQueue(LinkQueue &link) {
link.front = link.rear = (QueuePtr)malloc(sizeof(QNode));
if (!link.front) {
exit(-1); // 内存分配失败
}
link.front->next = NULL;
}
// 入队
void enQueue(LinkQueue &queue, int element) {
QueuePtr p = (QueuePtr)malloc(sizeof(QNode)); // 申请内存空间
if (!p) {
exit(-1); // 内存分配失败
}
p->data = element;
p->next = NULL;
queue.rear->next = p;
queue.rear = p;
}
// 出队
int deQueue(LinkQueue &queue, int &element) {
if (queue.rear == queue.front) {
return 0; // 队列为空
}
QueuePtr p = queue.front->next;
element = p->data;
queue.front->next = p->next;
if (queue.rear == p) {
queue.rear = queue.front;
}
free(p);
return 1;
}
// 销毁队列
void destroyQueue(LinkQueue &queue) {
QueuePtr p, q;
p = queue.front;
while (p) {
q = p->next;
free(p);
p = q;
}
queue.front = queue.rear = nullptr; // 将队首和队尾指针置为空指针
}
// 清空队列
void clearQueue(LinkQueue &queue) {
QueuePtr p = queue.front->next;
while (p) {
QueuePtr temp = p;
p = p->next;
free(temp);
}
queue.front->next = nullptr;
queue.rear = queue.front;
}
// 判断队列是否为空
bool isEmptyQueue(LinkQueue queue) {
return queue.front == queue.rear;
}
// 获取队列长度
int queueLength(LinkQueue queue) {
int length = 0;
QueuePtr p = queue.front->next;
while (p) {
length++;
p = p->next;
}
return length;
}
// 获取队列的头元素
int getFront(LinkQueue queue) {
if (isEmptyQueue(queue)) {
cout << "队列为空!" << endl;
return -1;
}
return queue.front->next->data;
}
// 输出队列元素
void printQueue(LinkQueue queue) {
QueuePtr p = queue.front->next;
while (p) {
cout << p->data << " ";
p = p->next;
}
cout << endl;
}
int main() {
LinkQueue queue;
initQueue(queue); // 初始化队列
// 测试入队
enQueue(queue, 10);
enQueue(queue, 20);
enQueue(queue, 30);
// 输出队列元素
cout << "队列元素:";
printQueue(queue);
// 测试出队
int element;
if (deQueue(queue, element)) {
cout << "出队元素:" << element << endl;
} else {
cout << "队列为空,无法出队!" << endl;
}
// 输出队列元素
cout << "队列元素:";
printQueue(queue);
// 清空队列
clearQueue(queue);
// 测试是否为空
if (isEmptyQueue(queue)) {
cout << "队列已清空或为空" << endl;
} else {
cout << "队列不为空" << endl;
}
// 测试队列长度
cout << "队列长度为:" << queueLength(queue) << endl;
// 测试获取队列头元素
cout << "队列头元素为:" << getFront(queue) << endl;
return 0;
}
3.线性表、栈、队列的区别
相同点:逻辑结构相同,都是线性的;都可以用顺序存储或者链式存储;栈和队列都是两种特殊的线性表,即受限的线性表(知识对插入、删除运算加以限制)。
不同点:
1.运算规则不同
线性表为随机存储,栈只允许在一段进行插入和删除运算,因而是后进先出表LIFO。
队列是只允许在一段进行插入、另一端进行删除操作,因而是先进先出表FIFO。
2.用途不同
线性表比较通用;堆栈用于函数调用、递归和简化设计等;队列用于离散事件模拟、OS作业调度和简化设计等。