上集回顾:链式存储队列
观看本系列博文提醒:
你将学会队列的两种最基本的表现形式:顺序存储队列 和 链式存储队列;
一个扩展队列的使用方法:循环队列;
两个企业级队列的应用:线性池中的任务队列 和 优先链式存储队列。
队列的原理
队列是一种受限的线性表,(Queue),它是一种运算受限的线性表,先进先出(FIFO First In First Out).
例如上图中,圆球1先进,也是圆球1先出。
队列是一种受限的线性结构
- 它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作。
- 生活中队列场景随处可见: 比如在电影院, 商场, 或者厕所排队。。。。。。
由上图我们可以知道,队列中有两个“指针”,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;
}
运行截图:
注意:由于一篇博客内容太多,所以我将会把他分成几篇进行讲解!
祝各位学习愉快!
下集预告:
你将学会一个扩展队列的使用方法:循环队列;
请持续关注!