关于 C++ 队列算法,你该了解这些【第三集:线性池中的任务队列】

上集回顾:链式存储队列

第一集:顺序存储队列
第二集:链式存储队列


观看本系列博文提醒:
你将学会队列的两种最基本的表现形式:顺序存储队列链式存储队列
一个扩展队列的使用方法:循环队列
两个企业级队列的应用:线性池中的任务队列优先链式存储队列


队列的原理

队列是一种受限的线性表,(Queue),它是一种运算受限的线性表,先进先出(FIFO First In First Out).
在这里插入图片描述
例如上图中,圆球1先进,也是圆球1先出。

队列是一种受限的线性结构

  1. 它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作。
  2. 生活中队列场景随处可见: 比如在电影院, 商场, 或者厕所排队。。。。。。

在这里插入图片描述
由上图我们可以知道,队列中有两个“指针”,front指向队首,rear指向队尾;
至于length,他是整个队列的总长度(因为一个队列他是有固定长度的)。


线性池中的任务队列

线程池 - 由一个任务队列和一组处理队列的线程组成。一旦工作进程需要处理某个可能“阻塞”的操作,不用自己操作,将其作为一个任务放到线程池的队列,接着会被某个空闲线程提取处理。
在这里插入图片描述

简单来说,就是节点出队时,函数指针调用的函数处理一系列的任务!

这算是上一集链式存储队列的练习题吧!

他的代码和链式存储队列的代码几乎完全一样,只是的节点多定义了一个函数指针,用于存储函数的地址。代码上也多了一些。
但是总体设计,总体思路都还是一样的。

代码如下:

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

using namespace std;

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

//typedef int DateType;	// 队列中元素的类型

typedef struct _QNode {	// 节点结构
	int id;				// 编号id
	void (*handler)();	// 函数指针
	struct _QNode* next;
}QNode;

typedef QNode* QueuePar;

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

// 队列的初始化
bool inItLinkQueue(LinkQueue*& LQ) {
	if (!LQ) {
		cout << "队列不存在!" << endl;
		return false;
	}

	LQ->lenght = 0;		// 队列长度值为零
	LQ->front = LQ->rear = NULL;	// 把队首和队尾指针指向NULL
	return true;
}

// 判断队列是否为空
bool estimateLinkQueueEmpty(LinkQueue*& LQ) {
	if (!LQ) {
		cout << "队列不存在!" << endl;
		return false;
	}

	if (!LQ->front) {
		return true;
	}

	return false;
}

// 判断队列是否已满
bool estimateLinkQueuefull(LinkQueue*& LQ) {
	if (!LQ) {
		cout << "队列不存在!" << endl;
		return false;
	}

	if (LQ->lenght == MaxSize) {
		return true;
	}

	return false;
}

// 入队,将元素插入队列中
bool linkQueueInsertValue(LinkQueue*& LQ, QNode*& NQ) {
	if (!LQ || !NQ) {
		cout << "队列不存在!" << endl;
		return false;
	}

	if (estimateLinkQueuefull(LQ)) {
		cout << "队列已满!" << endl;
		return false;
	}

	NQ->next = NULL;

	if (!LQ->front) {
		LQ->front = LQ->rear = NQ;
	} else {
		LQ->rear->next = NQ;
		LQ->rear = NQ;
	}

	LQ->lenght += 1;

	return true;
}

// 出队,删除队首
QNode* deleteLinkQueueFront(LinkQueue*& LQ) {
	if (!LQ) {
		cout << "队列不存在!" << endl;
		return 0;
	}

	if (estimateLinkQueueEmpty(LQ)) {
		cout << "链表为空!删除失败!" << endl;
		return 0;
	}

	QNode* tem = NULL;

	tem = LQ->front;

	LQ->front = LQ->front->next;
	if (!LQ->front) {
		LQ->rear = NULL;
	}

	LQ->lenght -= 1;

	return tem;
}

// 输出队列中的元素
bool linkQueuePrint(LinkQueue*& LQ) {
	if (!LQ) {
		cout << "队列不存在!" << endl;
		return false;
	}

	if (estimateLinkQueueEmpty(LQ)) {
		cout << "链表为空!输出失败!" << endl;
		return false;
	}

	QNode* tem = LQ->front;	// 定义临时节点指向队首指针

	cout << "id为: ";
	while (tem) {
		cout << tem->id << "\t";
		tem = tem->next;
	}
	cout << endl;

	return true;
}

//分配线程执行的任务节点
QNode* thread_task_alloc() {
	QNode* tem = new QNode;	// 分配内存

	if (!tem) {	// 判断是否分配失败
		return 0;
	}

	return tem;	// 返回节点指针
}

void text1(void) {
	cout << "第一个函数!" << endl;
}

void text2(void) {
	cout << "第二个函数!" << endl;
}

int main(void) {
	LinkQueue* LQ = new LinkQueue;
	QNode* tem = NULL;

	
	inItLinkQueue(LQ);

	// 任务一入队
	tem = thread_task_alloc();
	tem->id = 1;
	tem->handler = &text1;
	linkQueueInsertValue(LQ, tem);

	// 任务二入队
	tem = thread_task_alloc();
	tem->id = 2;
	tem->handler = &text2;
	linkQueueInsertValue(LQ, tem);

	cout << "队列的元素有:" << LQ->lenght << "个" << endl;
	linkQueuePrint(LQ);

	while (tem = deleteLinkQueueFront(LQ)) {
		tem->handler();
		delete tem;
	}
	
	
	delete LQ;
	system("pause");
	return 0;
}

运行截图:
在这里插入图片描述


注意:由于一篇博客内容太多,所以我将会把他分成几篇进行讲解!

祝各位学习愉快!


下集预告:
你将学会一个扩展队列的使用方法:循环队列
请持续关注!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章