用队列实现五个企业级应用,分别为循环队列,任务队列,优先队列,以及一个队列的应用案例(高并发服务器中队列的应用)。
1:循环队列
项目需求:在银行的排队系统中用户在银行进行办理业务用户可以进行取票后经行排队,如果我们定义一个一般的队列,如果用户有很多我们就要准备一个很长的队列,而循环队列可以实现用户的出队以后还可以经行用户的入队,这样可以实现资源的节约和效率的提升。
(1)循环队列和一般队列的实现有所不同,循环队列可以实现队列中的元素出对以后继续向队列中插入元素,而一般队列进行元素出队以后就不能实现元素的继续入队只能重启程序才能进行元素的入队。
(2)循环队列实现的具体思路:怎样才能实现循环队列?实现循环队列我们只需要让指向队尾的beak在进行元素入队时当入队到最后一个元素又能指向对头(因为每进行一次元素的入队back就往后移动一个位置直到入队到最后一个位置,如果让back移动到最后一个位置以后还能指向第一个位置就可以实现循环队列)。
循环队列的图像效果
把循环队列联想成一个圆盘就很容易实现循环队列。
(3)跟据上面的图像效果我们首先我们要做的是定义一个结构体来表示 这个循环队列,循环队列的结构体的定义和一般队列结构体定义(用数组形式实现是一样的)。
代码实现:
typedef struct circularQueue {
int date[MAXSIZE];
int front;
int back;
}circularQueue;
MAXSIZE是最大的入队元素个数(假如最多入队5个元素我们可以循环入队5个元素)
(4)定义完队列的结构体我们要做的是循环队列的初始化
//初始化循环队列
bool initcircularQueue(circularQueue*& queue) {
queue = new circularQueue;
if (!queue)return false; //内存分配失败
queue->back = 0;
queue->front = 0;
return true;
}
循环队列的初始化和一般队列的初始化一样都是将指向对头的front和指向队尾的beak都设置为0,再给定义好的结构体分配一块内存用来保存入队元素的值。
(5)初始化完队列我们要做的是进行队列元素的入队
//循环队列中元素的插入
bool insertcircularQueue(circularQueue*& queue, int i) {
if (!queue || isFull(queue))return false;
queue->date[queue->back] = i;
queue->back = (queue->back + 1) % MAXSIZE;
return true;
}
理解代码
queue->back = (queue->back + 1) % MAXSIZE;
我们为什么要定义成这样呢?beak我们初始化为0,随着元素的入队beak就要往后移动(每入队一个元素beak就加一)当beak入队到最大入队个数5时(queue->back + 1) % MAXSIZE=0 beak又指向了第一个入队的位置0,这样就可以实现元素的循环入队。
(6)元素入完对以后我们要做的时元素的打印
//打印循环队列中的元素
bool printcircularQueue(circularQueue*& queue) {
if (!queue || isEmpty(queue))return false;
int i;
i = queue->front;
while (queue->back != i) {
cout << queue->date[i] << " ";
i = (i + 1) % MAXSIZE;
}
return true;
}
理解:以下内容是本人在实现循环队列元素打印时踩的坑,在实现队列元素打印时我们都是用一个临时的指针来指向front,进而经行元素的打印,但我忘记了我定义的是指针而且定义的这个指针是指向我们刚才分配的那块内存,当我们遍历这个数组时随着往后移动front的值也随着改变直到移动到最后一个元素的位置front的值也改变为4,这会为以后元素的出队造成影响因为元素的出队是从第一个位置出队的,而我们以上的操作已经让front指向了最后一个位置所以就无法出队。所以用以上的操作(i = queue->front)把front的值赋值给我们定义的 i,这样当我们遍历完数组front依然指向第一个位置0这样就不会对我们元素的出队造成影响。
(7)队列元素的出队的实现
//删除循环队列中的元素
bool deleteCircularQueue(circularQueue*& queue) {
if (!queue || isEmpty(queue))return false;
queue->front = (queue->front + 1) % MAXSIZE;
return true;
}
(8)获得队首元素的值
//得到队首元素的值
bool getFrontValue(circularQueue*& queue) {
int i;
if (isEmpty(queue) || !queue) return false;
i = queue->date[queue->front];
cout << " 队首的值为: " << i << endl;
return true;
}
(9)获得队列的长度
//得到循环队列的长度
bool getCircuarQueueLength(circularQueue*& queue) {
if (isEmpty(queue) || !queue) return false;
cout << "队首位置为: " << queue->front;
cout << " 队尾位置为: " << queue->back;
int length = 0;
length = (queue->back - queue->front + MAXSIZE) % MAXSIZE;
cout << " 队列长度为:" << length << endl;
return true;
}
(10)清空队列
//清空循环队列
bool destoryQueue(circularQueue*& queue) {
if (isEmpty(queue) || !queue) return false;
queue->back = queue->front = 0;
re
循环队列代码具体main函数实现
#include<iostream>
#include<stdlib.h>
#include"circularQueue.h"
using namespace std;
int main(void) {
int c = 0;
circularQueue* queue;
initcircularQueue(queue);
for (int i = 1;i <= 10;i++) {
insertcircularQueue(queue, i);
}
printcircularQueue(queue);
getCircuarQueueLength(queue);
getFrontValue(queue);
cout << endl;
for (int j = 1;j <= 2;j++) {
deleteCircularQueue(queue);
}
printcircularQueue(queue);
getCircuarQueueLength(queue);
getFrontValue(queue);
cout << endl;
for (int i = 0;i <= 2;i++) {
insertcircularQueue(queue, i);
}
printcircularQueue(queue);
getCircuarQueueLength(queue);
getFrontValue(queue);
cout << endl;
system("pause");
return true;
}
头文件的实现
#include<iostream>
#pragma once
using namespace std;
#define MAXSIZE 5
typedef struct circularQueue {
int date[MAXSIZE];
int front;
int back;
}circularQueue;
//初始化循环队列
bool initcircularQueue(circularQueue*& queue) {
queue = new circularQueue;
if (!queue)return false; //内存分配失败
queue->back = 0;
queue->front = 0;
return true;
}
//判断循环队列是否为满
bool isFull(circularQueue*& queue) {
if ((queue->back + 1) % MAXSIZE == queue->front) return true;
return false;
}
//判断循环队列是否为空
bool isEmpty(circularQueue*& queue) {
if (queue->back == queue->front)return true;
return false;
}
//循环队列中元素的插入
bool insertcircularQueue(circularQueue*& queue, int i) {
if (!queue || isFull(queue))return false;
queue->date[queue->back] = i;
queue->back = (queue->back + 1) % MAXSIZE;
return true;
}
//打印循环队列中的元素
bool printcircularQueue(circularQueue*& queue) {
if (!queue || isEmpty(queue))return false;
int i;
i = queue->front;
while (queue->back != i) {
cout << queue->date[i] << " ";
i = (i + 1) % MAXSIZE;
}
return true;
}
//删除循环队列中的元素
bool deleteCircularQueue(circularQueue*& queue) {
if (!queue || isEmpty(queue))return false;
queue->front = (queue->front + 1) % MAXSIZE;
return true;
}
//得到循环队列的长度
bool getCircuarQueueLength(circularQueue*& queue) {
if (isEmpty(queue) || !queue) return false;
cout << "队首位置为: " << queue->front;
cout << " 队尾位置为: " << queue->back;
int length = 0;
length = (queue->back - queue->front + MAXSIZE) % MAXSIZE;
cout << " 队列长度为:" << length << endl;
return true;
}
//清空循环队列
bool destoryQueue(circularQueue*& queue) {
if (isEmpty(queue) || !queue) return false;
queue->back = queue->front = 0;
return true;
}
//得到队首元素的值
bool getFrontValue(circularQueue*& queue) {
int i;
if (isEmpty(queue) || !queue) return false;
i = queue->date[queue->front];
cout << " 队首的值为: " << i << endl;
return true;
}
2 队列的第应用任务队列
项目需求:在软件中软件功能的实现都是用函数实现的,从而我们可以将函数放入队列中经行实现,在线程池中每一个线程对应队列中的一个节点,而一个节点中有一个函数用来实现功能,所以任务队列在线程池中也可以应用。
(1)其实任务队列和一般队列(用链式实现的队列不是数组的方式)的用法相同就是在任务队列的结构体中在定义一个函数指针(用来指向定义好的函数),这样就可以实现函数的入队。
(2)结构体的定义
//表示队列的节点
typedef struct queueNode {
int i;
void (*fd)(void); //定义一个函数指针表示任务队列中的功能函数
struct queueNode* next;
}Node;
//表示队列的队头
typedef struct queueHead {
int length;
struct queueNode* front;
struct queueNode* beak;
}Head;
任务队列的实现和一般队列的实现没有什么不同,就不再经行讲解
(3)任务队列的初始化
//初始化队列的对头
bool initTestQueue(Head*& queueHead) {
queueHead = new Head;
if (!queueHead)return false;
queueHead->beak = queueHead->front = NULL;
queueHead->length = 0;
return true;
}
(4)任务队列的函数入队
//向队列中插入节点
bool insertTestQueue(Head*& queueHead, Node*& queueNode) {
if (!queueHead || !queueNode || isFull(queueHead))return false;
if (isEmpty(queueHead)) {
queueHead->front = queueNode;
queueHead->beak = queueNode;
queueNode->next = NULL;
queueHead->length++;
}
else {
queueHead->beak->next = queueNode;
queueNode->next = NULL;
queueHead->beak = queueNode;
queueHead->length++;
}
return true;
}
(5)判断队列是否为空
//判断队列是否为空
bool isEmpty(Head*& queueHead) {
if (queueHead->beak == NULL && queueHead->front == NULL)return true;
return false;
}
(6)判断队列是否为满
//判断队列是否为满
bool isFull(Head*& queueHead) {
if (queueHead->length == MAXSIZE)return true;
return false;
}
(7)任务队列函数功能的实现
//打印队列中的元素
bool printTestQueue(Head*& queueHead) {
if (!queueHead || isEmpty(queueHead))return false;
Node* p;
p = queueHead->front;
while (p) {
p->fd();
p = p->next;
}
return true;
}
(8)任务队列函数功能的关闭
//删除队列中的元素
bool deleteTestQueue(Head*& queueHead) {
if (!queueHead || isEmpty(queueHead))return false;
if (!queueHead->front) return false;
Node* p = queueHead->front;
queueHead->front = queueHead->front->next;
queueHead->length--;
delete p;
return true;
}
(9)得到队列的长度
//得到队列的长度
bool getTestQueueLength(Head*& queueHead) {
if (!queueHead || isEmpty(queueHead))return false;
cout << " 队列长度为:" << queueHead->length << endl;
return true;
}
main函数的实现
#include<stdlib.h>
#include<iostream>
#include"teskQueue.h"
int main(void) {
Head* queueHead;
initTestQueue(queueHead);
Node* queueNode;
queueNode = new Node;
queueNode->fd = &test1;
insertTestQueue(queueHead, queueNode);
Node* queueNode2;
queueNode2 = new Node;
queueNode2->fd = &test2;
insertTestQueue(queueHead, queueNode2);
printTestQueue(queueHead);
getTestQueueLength(queueHead);
system("pause");
return 0;
}
头文件的实现
#pragma once
#include<iostream>
#define MAXSIZE 100
using namespace std;
//表示队列的节点
typedef struct queueNode {
int i;
void (*fd)(void); //定义一个函数指针表示任务队列中的功能函数
struct queueNode* next;
}Node;
//表示队列的队头
typedef struct queueHead {
int length;
struct queueNode* front;
struct queueNode* beak;
}Head;
//测试函数1
void test1() {
cout << "函数一测试成功" << endl;
}
//测试函数2
void test2() {
cout << "函数二测试成功" << endl;
}
//初始化队列的对头
bool initTestQueue(Head*& queueHead) {
queueHead = new Head;
if (!queueHead)return false;
queueHead->beak = queueHead->front = NULL;
queueHead->length = 0;
return true;
}
//判断队列是否为空
bool isEmpty(Head*& queueHead) {
if (queueHead->beak == NULL && queueHead->front == NULL)return true;
return false;
}
//判断队列是否为满
bool isFull(Head*& queueHead) {
if (queueHead->length == MAXSIZE)return true;
return false;
}
//向队列中插入节点
bool insertTestQueue(Head*& queueHead, Node*& queueNode) {
if (!queueHead || !queueNode || isFull(queueHead))return false;
if (isEmpty(queueHead)) {
queueHead->front = queueNode;
queueHead->beak = queueNode;
queueNode->next = NULL;
queueHead->length++;
}
else {
queueHead->beak->next = queueNode;
queueNode->next = NULL;
queueHead->beak = queueNode;
queueHead->length++;
}
return true;
}
//打印队列中的元素
bool printTestQueue(Head*& queueHead) {
if (!queueHead || isEmpty(queueHead))return false;
Node* p;
p = queueHead->front;
while (p) {
p->fd();
p = p->next;
}
return true;
}
//得到队列的长度
bool getTestQueueLength(Head*& queueHead) {
if (!queueHead || isEmpty(queueHead))return false;
cout << " 队列长度为:" << queueHead->length << endl;
return true;
}
//删除队列中的元素
bool deleteTestQueue(Head*& queueHead) {
if (!queueHead || isEmpty(queueHead))return false;
if (!queueHead->front) return false;
Node* p = queueHead->front;
queueHead->front = queueHead->front->next;
queueHead->length--;
delete p;
return true;
}
3 优先队列的实现
项目需求:在上面我们实现了循环队列用来实现银行的排队取号系统,但是在因银行中有一些时VIP客户所以银行要进行优先处理。在进行入队时不管是VIP还是普通用户都进行正常入队,但是在出队时要对VIP用户进行优先处理。
(1)优先队列结构体的定义
//表示队列的节点
typedef struct firstQueueNode {
int first; //表示优先级
int fd; //保存队列中的数据
struct firstQueueNode* next; //指向下一个节点
}queueNode;
//表示队列的队头
typedef struct firstQueueHead {
int length;
struct firstQueueNode* front;
struct firstQueueNode* rear;
}queueHead;
优先队列和一般队列的定义差不多一样但是多了一个优先级来保存用户的等级,在出队的时候可以对VIP用户进行优先处理。
(2)对优先队列进行初始化
//初始化队列
bool initFirstQueue(queueHead*& Head) {
Head = new queueHead;
if (!Head)return false;
Head->front = NULL;
Head->rear = NULL;
Head->length = 0;
return true;
}
(3)对优先队列进行元素的插入
//向队列中插入元素
bool insertFirstQueue(queueHead*& Head, queueNode*& Node) {
if (!Head || isFull(Head))return false;
if (isEmpty(Head)) {
Head->front = Node;
Head->rear = Node;
Node->next = NULL;
Head->length++;
}
else {
Head->rear->next = Node;
Node->next = NULL;
Head->rear = Node;
Head->length++;
}
return true;
}
(4)判断队列是否为空和为满
//判断队列是否为空
bool isEmpty(queueHead*& Head) {
if (!Head)return false;
if (Head->front == NULL && Head->rear == NULL)return true;
return false;
}
//判断队列是否为满
bool isFull(queueHead*& Head) {
if (!Head)return false;
if (Head->length == MAXSIZE)return true;
return false;
}
(5)优先队列元素的出队
//删除优先队列中的元素
bool deleteFirstQueue(queueHead*& Head, int &date) {
queueNode** prev = NULL, * last = NULL;
queueNode* tmp = NULL, * prev_node = NULL;
if (!Head || isEmpty(Head))return false;
prev = &Head->front;
last = Head->front;
tmp = last->next;
while (tmp) {
if (tmp->first > (*prev)->first) {
prev = &(last->next);
prev_node = last;
}
last = tmp;
tmp = tmp->next;
}
date = (*prev)->first;
tmp = (*prev);
(*prev) = (*prev)->next;
delete tmp;
Head->length--;
if (Head->length == 0) {
Head->rear = NULL;
}
if (prev_node && prev_node == NULL) {
Head->rear = prev_node;
}
return true;
}
由于这个出队程序的逻辑比较复杂,情况较多本人就不在做过多解释
具体代码实现main文件实现
#include<stdlib.h>
#include"firstQueue.h"
int main(void) {
queueHead* Head = NULL;
initFirstQueue(Head);
for (int i = 1;i <= 5;i++) {
queueNode* Node;
Node = new queueNode;
Node->fd = i;
insertFirstQueue(Head, Node);
}
printFirstQueue(Head);
getFirstQueue(Head);
system("pause");
return true;
}
头文件的实现
#pragma once
#include<iostream>
using namespace std;
#define MAXSIZE 100
//表示队列的节点
typedef struct firstQueueNode {
int first; //表示优先级
int fd; //保存队列中的数据
struct firstQueueNode* next; //指向下一个节点
}queueNode;
//表示队列的队头
typedef struct firstQueueHead {
int length;
struct firstQueueNode* front;
struct firstQueueNode* rear;
}queueHead;
//初始化队列
bool initFirstQueue(queueHead*& Head) {
Head = new queueHead;
if (!Head)return false;
Head->front = NULL;
Head->rear = NULL;
Head->length = 0;
return true;
}
//判断队列是否为空
bool isEmpty(queueHead*& Head) {
if (!Head)return false;
if (Head->front == NULL && Head->rear == NULL)return true;
return false;
}
//判断队列是否为满
bool isFull(queueHead*& Head) {
if (!Head)return false;
if (Head->length == MAXSIZE)return true;
return false;
}
//向队列中插入元素
bool insertFirstQueue(queueHead*& Head, queueNode*& Node) {
if (!Head || isFull(Head))return false;
if (isEmpty(Head)) {
Head->front = Node;
Head->rear = Node;
Node->next = NULL;
Head->length++;
}
else {
Head->rear->next = Node;
Node->next = NULL;
Head->rear = Node;
Head->length++;
}
return true;
}
//得到队列的长度
bool getFirstQueue(queueHead*& Head) {
if (isEmpty(Head) || !Head)return false;
cout << " 队列的长度为:" << Head->length << endl;
return true;
}
//删除队列中的元素
bool deleteQueue(queueHead*& Head) {
if (isEmpty(Head) || !Head)return false;
queueNode* p;
p = Head->front;
Head->front = Head->front->next;
delete p;
Head->length--;
return true;
}
//打印队列中的元素
bool printFirstQueue(queueHead*& Head) {
if (isEmpty(Head) || !Head)return false;
queueNode* p;
p = Head->front;
while (p) {
cout << p->fd << " ";
p = p->next;
}
return true;
}
//删除优先队列中的元素
bool deleteFirstQueue(queueHead*& Head, int &date) {
queueNode** prev = NULL, * last = NULL;
queueNode* tmp = NULL, * prev_node = NULL;
if (!Head || isEmpty(Head))return false;
prev = &Head->front;
last = Head->front;
tmp = last->next;
while (tmp) {
if (tmp->first > (*prev)->first) {
prev = &(last->next);
prev_node = last;
}
last = tmp;
tmp = tmp->next;
}
date = (*prev)->first;
tmp = (*prev);
(*prev) = (*prev)->next;
delete tmp;
Head->length--;
if (Head->length == 0) {
Head->rear = NULL;
}
if (prev_node && prev_node == NULL) {
Head->rear = prev_node;
}
return true;
}
4 web服务器中对队列的使用,使用队列经行文件超时文件处理和对读取失败文件的处理。