The principle and implementation of queue algorithm, and its enterprise-level application

First, the principle of the queue

Queue is a limited linear table, (Queue), it is a linear table with limited operations, first in first out (FIFO First In First Out)

  • A queue is a constrained linear structure

  • It only allows delete operations at the front end of the table (front), and insert operations at the back end (rear) of the table.

insert image description here

Queue scenes can be seen everywhere in life: such as queuing in cinemas, shopping malls, or toilets. . . . . .

Second, the algorithm implementation of the queue

Algorithm implementation of the queue 1: using an array

Sequential storage :

An array is used to save the elements of the queue, and a queue front pointer and a queue tail pointer rear are set up to point to the queue head and tail elements respectively. but

rear-front is the number of stored elements!

insert image description here

insert image description here

Defined as:

#define MaxSize 5 //队列的最大容量 

typedef int DataType; //队列中元素类型 

typedef struct Queue {
    
     
    DataType queue[MaxSize]; 
    int front; //队头指针 
    int rear; //队尾指针 
}SeqQueue;
#include <iostream>
#include <Windows.h>

using namespace std;

typedef int Datatype;	//队列中的元素类型
#define MAX_SIZE 5		//队列最大容量

typedef struct _Queue {
    
    
	Datatype queue[MAX_SIZE];
	int front;
	int rear;
}Queue;

//初始化队列
bool initQueue(Queue* &Q) {
    
    
	if(!Q) return false;
	Q->front = Q->rear =0;
	return true;
}

//判断队列是否为空
bool blankQueue(Queue* &Q) {
    
    
	if(!Q) return false;
	if(Q->rear == Q->front) return true;
	return false;
}

//判断队列是否塞满
bool isFullQueue(Queue* &Q, Datatype data) {
    
    
	if(!Q) return false;
	if(Q->rear == MAX_SIZE) {
    
    
		cout << "队列已满,不能将" << data << "排进队列" << endl;	
		return true;
	}
	return false;
}

//排进队列
void queueUp(Queue* &Q, Datatype data) {
    
    
	if(!Q) return;
	if(isFullQueue(Q, data)) return;
	Q->queue[Q->rear] = data;
	Q->rear++;
}

//删除队首: 方法一
bool deleteQueueFirst(Queue* &Q, int *data) {
    
    
	if(!Q || blankQueue(Q)){
    
    
		cout << "队列为空!" << endl;
		return false;
	}
	if(!data) return false;

	int i = Q->front;
	--Q->rear;
	*data = Q->queue[Q->front];
	while(i != Q->rear) {
    
    
		Q->queue[i] = Q->queue[i+1];
		i++;
	}
	return false;
}

//删除队首: 方法二
bool deleteQueueFirst2(Queue* &Q, int *data) {
    
    
	if(!Q || blankQueue(Q)){
    
    
		cout << "队列为空!" << endl;
		return false;
	}
	if(!data) return false;
	if(Q->front == Q->rear) {
    
    
		cout << "队列已到尽头!" << endl;
		return false;
	}

	*data = Q->queue[Q->front];
	Q->front++;
	return true;
}

//获取队首元素
bool getFirstElem(Queue* &Q, Datatype *data) {
    
    
	if(!Q || blankQueue(Q)){
    
    
		cout << "队列为空!" << endl;
		return false;
	}
	if(!data) return false;

	*data = Q->queue[Q->front];
	return true;
}

//队列的长度
int OueueLength(Queue* &Q) {
    
    
	if(!Q) return 0;
	return Q->rear - Q->front;
}

//清空队列
void deleteQueue(Queue* Q) {
    
    
	Q->front = Q->rear = 0;
}

//打印队列
void printfQueue(Queue* &Q) {
    
    
	if(!Q) return;
	cout << "打印队列:";
	if(Q->front == Q->rear) {
    
    
		cout << "队列已到尽头!" << endl;
		return ;
	}
	int i = Q->front;
	while(i != Q->rear) {
    
    
		cout << Q->queue[i] << " ";
		i++;
	}
	cout << endl;
}

int main(void) {
    
    
	Queue *Q = new Queue;
	int data;

	//初始化队列
	initQueue(Q);

	for(int i=0; i<7; i++) {
    
    
		queueUp(Q, i);
	}
	printfQueue(Q);

	for(int i=0; i<10; i++) {
    
    
		if(deleteQueueFirst2(Q, &data))
			cout << "出队的元素是:" << data << endl;

		if(getFirstElem(Q, &data))
			cout << "队首的元素是:" << data << endl;
		printfQueue(Q);
	}

	system("pause");
	return 0;
}

Algorithm implementation of the queue 2: using a linked list

Chain storage :

The chained storage structure of the queue is actually a single-linked list of a linear table, but it is only tail-in and head-out. We refer to it as a chain queue for short. for

For operational convenience, we point the queue head pointer to the head node of the chain queue, and the queue tail pointer to the terminal node.

insert image description here

Defined as:

typedef int DataType; //队列中元素类型 

typedef struct _QNode {
    
     //结点结构 
DataType data; 
	struct _QNode *next; 
}QNode; 

typedef QNode * QueuePtr; 

typedef struct Queue {
    
     
    int length; 	//队列的长度 
    QueuePtr front; //队头指针 
    QueuePtr rear; 	//队尾指针 
}LinkQueue;

When the queue is empty, both front and rear point to empty.

insert image description here

#include <iostream>
#include <Windows.h>

using namespace std;

typedef int Datatype;	//队列中的数据类型
#define MAX_SIZE     5	//队列中的最大容量

typedef struct _QNode {
    
    
	Datatype data;
	struct _QNode *next;
}QNode;

typedef QNode* QueuePtr;

typedef struct _QueueLink {
    
    
	int length;		//队列长度
	QueuePtr front; //指向队首
	QueuePtr rear;	//指向队尾
}QueueLink;

//队列初始化
bool initQueueLink(QueueLink* &QL) {
    
    
	if(!QL) return false;
	QL->length = 0;
	QL->front = QL->rear = NULL;
	return true;
}

//判断队列是否为空
bool isBlankQueueLink(QueueLink* &QL) {
    
    
	if(!QL) return false;
	if(!QL->front) return true;
	return false;
}

//判断队列是否塞满
bool isFullQueueLink(QueueLink* &QL) {
    
    
	if(!QL) return false;
	if(QL->length == MAX_SIZE) return true;
	return false;
}

//元素进入队列
bool enterElemQueueLink(QueueLink* &QL, Datatype data) {
    
    
	if(!QL) return false;
	if(isFullQueueLink(QL)) {
    
    
		cout << "队列已满!无法将元素" << data << "插入到队列中!" << endl;
		return false;
	}
	QNode* node = new QNode;
	node->data = data;

	if(isBlankQueueLink(QL)) {
    
    
		QL->front = QL->rear = node;
	}else {
    
    
		QL->rear->next = node;
		QL->rear = node;
	}
	node->next = NULL;
	QL->length++;
	return true;
}

//元素出队列
bool deleteElemQueueLink(QueueLink* &QL, Datatype *data) {
    
    
	if(!QL || isBlankQueueLink(QL)) {
    
    
		cout << "队列为空" << endl;
		return false;
	}
	if(!data) return false;

	QNode *tmp = NULL;
	tmp = QL->front;

	QL->front = QL->front->next;
    if(!QL->front) QL->rear = NULL;
    
	*data = tmp->data;
	delete tmp;
	QL->length--;
	return true;
}

//获取队首元素
bool getFirstElemQueueLink(QueueLink* &QL, Datatype *data) {
    
    
	if(!QL || isBlankQueueLink(QL)) {
    
    
		cout << "队列为空" << endl;
		return false;
	}
	if(!data) return false;

	*data = QL->front->data;
	return true;
}

//清空队列
void clearQueueLink(QueueLink* &QL) {
    
    
	if(!QL || isBlankQueueLink(QL)) {
    
    
		cout << "队列为空" << endl;
		return;
	}

	QNode *p = QL->front;

	while(p) {
    
    
		cout << "删除" << p->data << endl;
		QL->front = QL->front->next;
		delete p;
		 p = QL->front;
	}
	/*while(QL->front){ 
		QueuePtr tmp = QL->front->next; 
		delete QL->front; 
		QL->front = tmp; 
	}*/

	QL->front = QL->rear = NULL;
	QL->length = 0;

}

//队列长度
int getLengthQueueLink(QueueLink* QL) {
    
    
	if(!QL || isBlankQueueLink(QL)) return 0;

	int i=0;
	QueuePtr p = QL->front;
	while(p) {
    
    
		i++;
		p = p->next;
	}
	return i;
}

//打印队列
void printfQueueLink(QueueLink* &QL) {
    
    
	cout << "打印队列:";
	if(!QL) return;
	if(isBlankQueueLink(QL)) return;
	
	QNode *p = QL->front;
	while(p) {
    
    
		cout << p->data << " ";
		p = p->next;
	}

	cout << endl;
}

int main(void) {
    
    
	QueueLink *QL = new QueueLink;
	initQueueLink(QL);
	int x = -2;

	for(int i=0; i<7; i++) {
    
    
		if(enterElemQueueLink(QL, i)) {
    
    
			cout << "添加[" << i << "]成功!" << endl;
		}else {
    
    
			cout << "添加失败!" << endl;
		}
		printfQueueLink(QL);
		if(getFirstElemQueueLink(QL, &x)) {
    
    
			cout << "获取队首元素【" << x << "】,成功!" << endl;
		}else{
    
    
			cout << "获取队首元素失败" << endl;
		}
		cout << "队列长度:" << getLengthQueueLink(QL) << endl;
		cout << endl;
	}

	/*int data = -1;
	for(int i=0; i<7; i++) {
		if(deleteElemQueueLink(QL, &data)) {
			cout << data << "出队成功!" << endl;
		}else {
			cout << "出队失败!" << endl;
		}
		printfQueueLink(QL);
		if(getFirstElemQueueLink(QL, &x)) {
			cout << "获取队首元素【" << x << "】,成功!" << endl;
		}else{
			cout << "获取队首元素失败" << endl;
		}
		cout << "队列长度:" << getLengthQueueLink(QL) << endl;
		cout << endl;
	}*/
	clearQueueLink(QL);
	printfQueueLink(QL);
	delete QL;
	system("pause");
	return 0;
}

3. Enterprise-level application cases of queues

One, the task queue in the thread pool

Thread Pool - Consists of a task queue and a set of threads that process the queue . Once a worker process needs to process a potentially "blocking"

Operation, do not need to operate by yourself, put it into the queue of the thread pool as a task, and then it will be extracted and processed by an idle thread.

insert image description here

Defined by:

typedef struct _QNode {
    
     //结点结构 
    int id; 
    void (*handler)(); 
    struct _QNode *next; 
}QNode; 

typedef QNode * QueuePtr; 

typedef struct Queue {
    
     
    int length; //队列的长度 
    QueuePtr front; //队头指针 
    QueuePtr rear; //队尾指针 
}LinkQueue;
#include <iostream>
#include <Windows.h>

using namespace std;

#define MAX_SIZE     5	//队列中的最大容量

typedef struct _QNode {
    
    
	int fd;
	void (*handler)();
	struct _QNode *next;
}QNode;

typedef QNode* QueuePtr;

typedef struct _QueueLink {
    
    
	int length;		//队列长度
	QueuePtr front; //指向队首
	QueuePtr rear;	//指向队尾
}QueueLink;

//分配线程中的任务节点
QueuePtr thread_task_alloc() {
    
    
	QNode *task = (QNode*)calloc(1, sizeof(QNode));;
	if(!task) return NULL;
	return task;
}

//队列初始化
bool initQueueLink(QueueLink* &QL) {
    
    
	if(!QL) return false;
	QL->length = 0;
	QL->front = QL->rear = NULL;
	return true;
}

//判断队列是否为空
bool isBlankQueueLink(QueueLink* &QL) {
    
    
	if(!QL) return false;
	if(!QL->front) return true;
	return false;
}

//判断队列是否塞满
bool isFullQueueLink(QueueLink* &QL) {
    
    
	if(!QL) return false;
	if(QL->length == MAX_SIZE) return true;
	return false;
}

//元素进入队列
bool enterElemQueueLink(QueueLink* &QL, QNode *node) {
    
    
	if(!QL || !node) return false;
	if(isFullQueueLink(QL)) {
    
    
		cout << "队列已满!无法将任务:" << node->handler << "插入到队列中!" << endl;
		return false;
	}

	if(isBlankQueueLink(QL)) {
    
    
		QL->front = QL->rear = node;
	}else {
    
    
		QL->rear->next = node;
		QL->rear = node;
	}
	node->next = NULL;
	QL->length++;
	return true;
}

//元素出队列
QueuePtr PopQueueLink(QueueLink* &QL) {
    
    
	if(!QL || isBlankQueueLink(QL)) {
    
    
		cout << "队列为空" << endl;
		return false;
	}

	QNode *tmp = NULL;
	tmp = QL->front;

	QL->front = tmp->next;
	if(!QL->front) QL->rear = NULL;

	QL->length--;
	return tmp;
}

//获取队首元素
QueuePtr getFirstElemQueueLink(QueueLink* &QL) {
    
    
	if(!QL || isBlankQueueLink(QL)) {
    
    
		cout << "队列为空" << endl;
		return NULL;
	}
	return QL->front;
}

//清空队列
void clearQueueLink(QueueLink* &QL) {
    
    
	if(!QL || isBlankQueueLink(QL)) {
    
    
		cout << "队列为空" << endl;
		return;
	}

	QNode *p = QL->front;

	while(p) {
    
    
		cout << "删除" << p->handler << endl;
		QL->front = QL->front->next;
		delete p;
		 p = QL->front;
	}
	/*while(QL->front){ 
		QueuePtr tmp = QL->front->next; 
		delete QL->front; 
		QL->front = tmp; 
	}*/

	QL->front = QL->rear = NULL;
	QL->length = 0;

}

//队列长度
int getLengthQueueLink(QueueLink* QL) {
    
    
	if(!QL || isBlankQueueLink(QL)) return 0;

	/*int i=0;
	QueuePtr p = QL->front;
	while(p) {
		i++;
		p = p->next;
	}*/
	return QL->length;
}

//打印队列
void printfQueueLink(QueueLink* &QL) {
    
    
	cout << "打印任务队列:";
	if(!QL) return;
	if(isBlankQueueLink(QL)) return;
	
	QNode *p = QL->front;
	while(p) {
    
    
		cout << p->fd << " ";
		p = p->next;
	}

	cout << endl;
}

void task1(){
    
     
	printf("我是任务 1 ...\n"); 
}

void task2(){
    
     
	printf("我是任务 2 ...\n"); 
}

int main(void) {
    
    
	QueueLink *QL = new QueueLink;

	//初始化队列
	initQueueLink(QL);

	//任务1入队
	QNode *task = thread_task_alloc();
	task->fd = 1;
	task->handler  = &task1;
	enterElemQueueLink(QL, task);

	//任务2入队
	task = thread_task_alloc();
	task->fd = 2;
	task->handler  = &task2;
	enterElemQueueLink(QL, task);

	cout << "队列中的任务长度为:" << getLengthQueueLink(QL) << endl;
	printfQueueLink(QL);
	cout << endl;

	//执行任务队列
	while((task=PopQueueLink(QL))) {
    
    
		task->handler();
		delete task;
	}

	delete QL;
	system("pause");
	return 0;
}

Second, the circular queue

circular queue

In the sequential storage of the queue, the dequeue method 2 is used to delete the element pointed to by front, then add 1 and return the deleted element. This avoids the element

Move, but it also brings a new problem " false overflow ".

insert image description here

Can you use the space in front to continue storing into the queue? Using a circular queue can solve this problem.

insert image description here

The circular queue enters the queue, and the tail of the queue moves backward : SQ->rear = (SQ->rear+1)%MAX_SIZE;

The cyclic queue is dequeued, and the head of the queue is moved backward : SQ->front = (SQ->front+1)%MAX_SIZE;

Empty : SQ.front=SQ.rear; // SQ.rear and SQ.front point to the same position

Queue full : (SQ.rear+1) %MAX_SIZE=SQ.front; // SQ.rear moves backward one bit exactly to SQ.front

Count the number of elements:

It can be judged in two cases:

  • If SQ.rear>= SQ.front: the number of elements is SQ.rear-SQ.front;

  • If SQ.rear<SQ.front: the number of elements is SQ.rear-SQ.front+ MAX_SIZE;

Use the modulus method to unify the two situations into: (SQ.rear-SQ.front+MAX_SIZE)% MAX_SIZE

#include <iostream>
#include <Windows.h>

using namespace std;

typedef int Datatype;	//队列中的元素类型
#define MAX_SIZE 5		//队列最大容量

typedef struct _Queue {
    
    
	Datatype queue[MAX_SIZE];
	int front;
	int rear;
}Queue;

//初始化队列
bool initQueue(Queue* &Q) {
    
    
	if(!Q) return false;
	Q->front = Q->rear =0;
	return true;
}

//判断队列是否为空
bool blankQueue(Queue* &Q) {
    
    
	if(!Q) return false;
	if(Q->rear == Q->front) return true;
	return false;
}

//判断队列是否塞满
bool isFullQueue(Queue* &Q) {
    
    
	if(!Q) return false;
	if((Q->rear + 1)%MAX_SIZE == Q->front) return true;
	return false;
}

//进入队列
void queueUp(Queue* &Q, Datatype data) {
    
    
	if(!Q) return;
	if(isFullQueue(Q)) {
    
    
	cout << "队列已满,不能将" << data << "排进队列" << endl;	
		return;
	}

	Q->queue[Q->rear] = data;
	Q->rear = (Q->rear + 1)%MAX_SIZE;
}

//删除队首
bool deleteQueueFirst(Queue* &Q, int *data) {
    
    
	if(!Q || blankQueue(Q)){
    
    
		cout << "队列为空!" << endl;
		return false;
	}
	if(!data) return false;
	
	*data = Q->queue[Q->front];
	Q->front = (Q->front+ 1)%MAX_SIZE;
	return true;
}

//获取队首元素
bool getFirstElem(Queue* &Q, Datatype *data) {
    
    
	if(!Q || blankQueue(Q)){
    
    
		cout << "队列为空!" << endl;
		return false;
	}
	if(!data) return false;

	*data = Q->queue[Q->front];
	return true;
}

//队列的长度
int OueueLength(Queue* &Q) {
    
    
	if(!Q) return 0;
	return (Q->rear - Q->front + MAX_SIZE)%MAX_SIZE;
}

//清空队列
void deleteQueue(Queue* Q) {
    
    
	Q->front = Q->rear = 0;
}

//打印队列
void printfQueue(Queue* &Q) {
    
    
	if(!Q || blankQueue(Q)){
    
    
		cout << "队列为空!" << endl;
		return ;
	}
	cout << "打印队列:";
	
	int i = Q->front;
	while(i != Q->rear) {
    
    
		cout << Q->queue[i] << " ";
		i = (i + 1)%MAX_SIZE;
	}
	cout << endl;
}

int main(void) {
    
    
	Queue *Q = new Queue;
	int data;

	//初始化队列
	initQueue(Q);

	for(int i=0; i<7; i++) {
    
    
		queueUp(Q, i);
	}
	cout << "队列长度:" << OueueLength(Q) << endl;
	printfQueue(Q);

	cout << endl;

	for(int i=0; i<5; i++) {
    
    
		if(deleteQueueFirst(Q, &data))
			cout << "出队的元素是:" << data << endl;

		if(getFirstElem(Q, &data))
			cout << "队首的元素是:" << data << endl;
		cout << "队列长度:" << OueueLength(Q) << endl;
		printfQueue(Q);
		cout << endl;
	}

	for(int i=0; i<7; i++) {
    
    
		queueUp(Q, i);
	}
	cout << "队列长度:" << OueueLength(Q) << endl;
	printfQueue(Q);

	cout << endl;

	for(int i=0; i<5; i++) {
    
    
		if(deleteQueueFirst(Q, &data))
			cout << "出队的元素是:" << data << endl;

		if(getFirstElem(Q, &data))
			cout << "队首的元素是:" << data << endl;
		cout << "队列长度:" << OueueLength(Q) << endl;
		printfQueue(Q);
		cout << endl;
	}
	
    delete Q;
    
	system("pause");
	return 0;
}

Three, priority queue

Priority queue :

Its order of entering the queue has not changed, but the order of dequeuing is determined according to the priority. high priority

Priority dequeuing.

Defined as:

typedef int Datatype;	//队列中的数据类型
#define MAX_SIZE     5	//队列中的最大容量

typedef struct _QNode {
    
    
	int priority;	//每个节点的优先级,9 最高优先级,0 最低优先级,优先级相同, 取第一个节点
	Datatype data;
	struct _QNode *next;
}QNode;

typedef QNode* QueuePtr;

typedef struct _QueueLink {
    
    
	int length;		//队列长度
	QueuePtr front; //指向队首
	QueuePtr rear;	//指向队尾
}QueueLink;

In the linked list queue, the code for dequeuing is mainly changed. After the change, it is as follows:

//元素出队列
bool deleteElemQueueLink(QueueLink* &QL, Datatype *data) {
    
    
	if(!QL || isBlankQueueLink(QL)) {
    
    
		cout << "队列为空" << endl;
		return false;
	}
	if(!data) return false;

	QNode **prev = NULL, *prev_node = NULL;
	QNode *tmp = NULL, *last = NULL;

	prev = &(QL->front);
	cout << "第一个结点的优先级是: " << (*prev)->priority << endl;
	
	last = QL->front;
	tmp = last->next;

	while(tmp) {
    
    
		if(tmp->priority > (*prev)->priority) {
    
    
			cout << "抓到一个更大的优先级:" << tmp->priority << endl;
			prev = &(last->next);
			prev_node = last;
		}
		last = tmp;
		tmp = tmp->next;
	}

	tmp = *prev;
	*prev = (*prev)->next;
	*data = tmp->data;
	delete tmp;
	QL->length--;

	//如果只有一个节点
    if(!QL->length) QL->rear = NULL;

	//如果删除的是最后一个节点
	//if(prev_node && !prev_node->next) QL->rear = prev_node; 与下面这个写法可以达到相同的效果
	if(!*prev) QL->rear = prev_node;
    
	return true;
}

Full code:

#include <iostream>
#include <Windows.h>

using namespace std;

typedef int Datatype;	//队列中的数据类型
#define MAX_SIZE     5	//队列中的最大容量

typedef struct _QNode {
    
    
	int priority;	//优先级
	Datatype data;
	struct _QNode *next;
}QNode;

typedef QNode* QueuePtr;

typedef struct _QueueLink {
    
    
	int length;		//队列长度
	QueuePtr front; //指向队首
	QueuePtr rear;	//指向队尾
}QueueLink;

//队列初始化
bool initQueueLink(QueueLink* &QL) {
    
    
	if(!QL) return false;
	QL->length = 0;
	QL->front = QL->rear = NULL;
	return true;
}

//判断队列是否为空
bool isBlankQueueLink(QueueLink* &QL) {
    
    
	if(!QL) return false;
	if(!QL->front) return true;
	return false;
}

//判断队列是否塞满
bool isFullQueueLink(QueueLink* &QL) {
    
    
	if(!QL) return false;
	if(QL->length == MAX_SIZE) return true;
	return false;
}

//元素进入队列
bool enterElemQueueLink(QueueLink* &QL, Datatype data, int priority) {
    
    
	if(!QL) return false;
	if(isFullQueueLink(QL)) {
    
    
		cout << "队列已满!无法将元素" << data << "插入到队列中!" << endl;
		return false;
	}
	QNode* node = new QNode;
	node->data = data;
	node->priority = priority;

	if(isBlankQueueLink(QL)) {
    
    
		QL->front = QL->rear = node;
	}else {
    
    
		QL->rear->next = node;
		QL->rear = node;
	}
	node->next = NULL;
	QL->length++;
	return true;
}

//元素出队列
bool deleteElemQueueLink(QueueLink* &QL, Datatype *data) {
    
    
	if(!QL || isBlankQueueLink(QL)) {
    
    
		cout << "队列为空" << endl;
		return false;
	}
	if(!data) return false;

	QNode **prev = NULL, *prev_node = NULL;
	QNode *tmp = NULL, *last = NULL;

	prev = &(QL->front);
	cout << "第一个结点的优先级是: " << (*prev)->priority << endl;
	
	last = QL->front;
	tmp = last->next;

	while(tmp) {
    
    
		if(tmp->priority > (*prev)->priority) {
    
    
			cout << "抓到一个更大的优先级:" << tmp->priority << endl;
			prev = &(last->next);
			prev_node = last;
		}
		last = tmp;
		tmp = tmp->next;
	}

	tmp = *prev;
	*prev = (*prev)->next;
	*data = tmp->data;
	delete tmp;
	QL->length--;

	//如果只有一个节点
    if(!QL->length) QL->rear = NULL;

	//如果删除的是最后一个节点
	//if(prev_node && !prev_node->next) QL->rear = prev_node; 与下面这个写法可以达到相同的效果
	if(!*prev) QL->rear = prev_node;
    
	return true;
}

//获取队首元素
bool getFirstElemQueueLink(QueueLink* &QL, Datatype *data) {
    
    
	if(!QL || isBlankQueueLink(QL)) {
    
    
		cout << "队列为空" << endl;
		return false;
	}
	if(!data) return false;

	*data = QL->front->data;
	return true;
}

//清空队列
void clearQueueLink(QueueLink* &QL) {
    
    
	if(!QL || isBlankQueueLink(QL)) {
    
    
		cout << "队列为空" << endl;
		return;
	}

	QNode *p = QL->front;

	while(p) {
    
    
		cout << "删除" << p->data << endl;
		QL->front = QL->front->next;
		delete p;
		 p = QL->front;
	}
	/*while(QL->front){ 
		QueuePtr tmp = QL->front->next; 
		delete QL->front; 
		QL->front = tmp; 
	}*/

	QL->front = QL->rear = NULL;
	QL->length = 0;

}

//队列长度
int getLengthQueueLink(QueueLink* QL) {
    
    
	if(!QL || isBlankQueueLink(QL)) return 0;

	/*int i=0;
	QueuePtr p = QL->front;
	while(p) {
		i++;
		p = p->next;
	}
	return i;*/
	return QL->length;
}

//打印队列
void printfQueueLink(QueueLink* &QL) {
    
    
	cout << "打印队列:";
	if(!QL) return;
	if(isBlankQueueLink(QL)) return;
	
	QNode *p = QL->front;
	while(p) {
    
    
		cout << p->data <<"["<< p->priority <<"]" << " ";
		p = p->next;
	}

	cout << endl;
}

int main(void) {
    
    
	QueueLink *QL = new QueueLink;
	initQueueLink(QL);
	int x = -2;


	if(enterElemQueueLink(QL, 8, 6)) {
    
    
			cout << "添加[" << 8 << "]成功!" << endl;
		}else {
    
    
			cout << "添加失败!" << endl;
		}
		printfQueueLink(QL);

		if(enterElemQueueLink(QL, 0, 9)) {
    
    
			cout << "添加[" << 0 << "]成功!" << endl;
		}else {
    
    
			cout << "添加失败!" << endl;
		}
		printfQueueLink(QL);

	for(int i=0; i<7; i++) {
    
    
		if(enterElemQueueLink(QL, i+10, i)) {
    
    
			cout << "添加[" << i+10 << "]成功!" << endl;
		}else {
    
    
			cout << "添加失败!" << endl;
		}
		printfQueueLink(QL);
		if(getFirstElemQueueLink(QL, &x)) {
    
    
			cout << "获取队首元素【" << x << "】,成功!" << endl;
		}else{
    
    
			cout << "获取队首元素失败" << endl;
		}
		cout << "队列长度:" << getLengthQueueLink(QL) << endl;
		cout << endl;
	}

	int data = -1;
	for(int i=0; i<7; i++) {
    
    
		if(deleteElemQueueLink(QL, &data)) {
    
    
			cout << data << "出队成功!" << endl;
		}else {
    
    
			cout << "出队失败!" << endl;
		}
		printfQueueLink(QL);
		if(getFirstElemQueueLink(QL, &x)) {
    
    
			cout << "获取队首元素【" << x << "】,成功!" << endl;
		}else{
    
    
			cout << "获取队首元素失败" << endl;
		}
		cout << "队列长度:" << getLengthQueueLink(QL) << endl;
		cout << endl;
	}
	clearQueueLink(QL);
	printfQueueLink(QL);

	delete QL;
	system("pause");
	return 0;
}

Four, dynamic sequential queue

The queue that uses the linked list to dynamically store is a dynamic sequential queue, which has been implemented before, so it will not be repeated!

Five, the application of high concurrent WEB server queue


In the high concurrent HTTP reverse proxy server Nginx, there is a module closely related to performance - file cache.

insert image description here

Frequently accessed files will be cached from disk to memory by nginx, which can greatly improve the concurrency capability of Nginx, but because

Due to the limitation of memory, when the number of cached files reaches a certain level, an elimination mechanism will be adopted, and priority will be given to eliminating files that have been entered for a long time or recently.

Queue files with few accesses (LRU).

Specific implementation plan:

  1. Use a two-way circular queue to save cached file nodes, which can implement multiple elimination strategies:

For example: If you adopt the strategy of eliminating entry time for a long time, you can use the characteristics of the queue, first in first out

If you want to use LRU, traverse the linked list and find the node to delete.

nginx_queue.h

#ifndef _NGX_QUEUE_H_INCLUDED_ 
#define _NGX_QUEUE_H_INCLUDED_ 

typedef struct ngx_queue_s ngx_queue_t; 

struct ngx_queue_s {
    
     
    	ngx_queue_t *prev; 
        ngx_queue_t *next; 
};

#define ngx_queue_init(q) \ 
		(q)->prev = q; \ 
    	(q)->next = q 
        
#define ngx_queue_empty(h) \ 
        (h == (h)->prev) 
        
#define ngx_queue_insert_head(h, x) \ 
        (x)->next = (h)->next; \ 
        (x)->next->prev = x; \ 
        (x)->prev = h; \ 
        (h)->next = x 

#define ngx_queue_insert_after 
        ngx_queue_insert_head 
        
#define ngx_queue_insert_tail(h, x) \ 
        (x)->prev = (h)->prev; \ 
        (x)->prev->next = x; \ 
        (x)->next = h; \ 
        (h)->prev = x 
        
#define ngx_queue_head(h) \ 
        (h)->next 
        
#define ngx_queue_last(h) \ 
        (h)->prev

#define ngx_queue_sentinel(h) \ 
        (h) 
        
#define ngx_queue_next(q) \ 
        (q)->next 
        
#define ngx_queue_prev(q) \ 
        (q)->prev 
        
#define ngx_queue_remove(x) \ 
        (x)->next->prev = (x)->prev; \ 
        (x)->prev->next = (x)->next 
        
#define ngx_queue_data(q, type, link) \ 
        (type *) ((char *) q - offsetof(type, link)) 
#endif

Nginx_two-way circular queue.cpp

#include <Windows.h> 
#include <stdlib.h> 
#include <iostream> 
#include "nginx_queue.h" 
#include <time.h> 

using namespace std; 

typedef struct ngx_cached_open_file_s {
    
     
    //其它属性省略... 
    int fd; 
    ngx_queue_t queue; 
}ngx_cached_file_t;

typedef struct {
    
     
    //其它属性省略... 
    ngx_queue_t expire_queue; 
    //其它属性省略... 
} ngx_open_file_cache_t; 

int main(void){
    
     
    ngx_open_file_cache_t *cache = new ngx_open_file_cache_t; 
    ngx_queue_t *q; 
    ngx_queue_init(&cache->expire_queue); //1. 模拟文件模块,增加打开的文件到缓存中 
    
    for(int i=0; i<10; i++){
    
     
        ngx_cached_file_t *e = new ngx_cached_file_t; 
        e->fd = i; 
        ngx_queue_insert_head(&cache->expire_queue, &e->queue); 
    }
    
    //遍历队列 
    for(q=cache->expire_queue.next; q!=ngx_queue_sentinel(&cache->expire_queue); 
        q=q->next){
    
     
        
        printf("队列中的元素:%d\n", (ngx_queue_data(q, ngx_cached_file_t, queue))->fd); 	  }
    
    //模拟缓存的文件到期,执行出列操作 
    while(!ngx_queue_empty(&cache->expire_queue)){
    
     
        q=ngx_queue_last(&cache->expire_queue); 
        ngx_cached_file_t *cached_file = ngx_queue_data(q, ngx_cached_file_t, queue); 		  printf("出队列中的元素:%d\n", cached_file->fd); ngx_queue_remove(q); 				delete(cached_file); 
    }
    system("pause"); 
    return 0; 
}

Guess you like

Origin blog.csdn.net/weixin_46060711/article/details/125077479