任务队列

任务队列是指能够实现任务在多线程间安全传递的先入先出的队列.

一个个不同的任务可以抽象化为函数,此时我们可以使用函数指针得到并处理他们.
任务队列的大致结构如下:
任务队列_第1张图片

结构体定义

提示:

  1. 每个任务都有自己的ID
  2. 使用函数指针存放任务
  3. 任务队列是先进先出的,因此我们还需要队头和队尾指针
typedef struct TQNode {
	int id;//每个任务都有自己的ID
	void (*handle)(void);//使用函数指针存放任务
	TQNode *next;
}TQNode;

typedef struct {//任务队列是先进先出的,因此我们还需要队头和队尾指针
	TQNode *front;
	TQNode *rear;
}Queue;

函数指针详解:

函数指针是指向函数的指针变量。 因此“函数指针”本身首先应是指针变量,只不过该指针变量指向函数。这正如用指针变量可指向整型变量、字符型、数组一样,这里是指向函数。如前所述,C在编译时,每一个函数都有一个入口地址,该入口地址就是函数指针所指向的地址。有了指向函数的指针变量后,可用该指针变量调用函数,就如同用指针变量可引用其他类型变量一样,在这些概念上是大体一致的。函数指针有两个用途:调用函数和做函数的参数。

使用方法:
返回值类型 ( * 指针变量名) ([形参列表]);
"返回值类型"说明了函数的返回类型,"指针变量名"为函数指针的名字,"形参列表"说明了传入函数的参数(若无参数可写void)

初始化

提示:

  1. 动态内存分配是否成功?
  2. 队头和队尾指针是否进行了初始化?
bool initQueue(Queue* &q) {
	q = new Queue;
	if (!q) {//动态内存分配是否成功?
		return false;
	}

	q->front = q->rear = NULL;//队头和队尾指针是否进行了初始化?
	return true;
}

插入元素

提示:

  1. 传入的队列是否有效?
  2. 传入元素可能为队列的第一个元素
void insertQueue(Queue *q,TQNode *e) {
	if (!q && !e) {//传入的队列是否有效?
		cout << "插入失败" << endl;
		return;
	}

	if (!q->front && !q->rear) {//传入元素可能为队列的第一个元素
		q->front = q->rear = e;
		return;
	}

	q->rear->next = e;
	q->rear = e;
}

删除元素

提示:

  1. 删除元素的时候应返回指向删除元素的地址(以便于运行其任务)
TQNode* deleteQueue(Queue *q) {
	TQNode *e;

	e = q->front;//删除元素的时候应返回指向删除元素的地址
	if (!e) {
		return NULL;
	}

	q->front = q->front->next;
	if (!q->front) {
		q->rear = NULL;
	}
	
	return e;
}

打印元素

无提示,选择自己喜欢的风格.

void printQueue(Queue *q) {
	TQNode *e;
	e = q->front;

	if (!e) {
		cout << "此队列为空!" << endl;
		return;
	}

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

全部代码及测试代码

此处测试了两个任务的运行情况.

#include 

using namespace std;

typedef struct TQNode {
	int id;
	void (*handle)(void);
	TQNode *next;
}TQNode;

typedef struct {
	TQNode *front;
	TQNode *rear;
}Queue;

bool initQueue(Queue* &q) {
	q = new Queue;
	if (!q) {
		return false;
	}

	q->front = q->rear = NULL;
	return true;
}

void insertQueue(Queue *q,TQNode *e) {
	if (!q && !e) {
		cout << "插入失败" << endl;
		return;
	}

	if (!q->front && !q->rear) {
		q->front = q->rear = e;
		return;
	}

	q->rear->next = e;
	q->rear = e;
}

TQNode* deleteQueue(Queue *q) {
	TQNode *e;

	e = q->front;
	if (!e) {
		return NULL;
	}

	q->front = q->front->next;
	if (!q->front) {
		q->rear = NULL;
	}
	
	return e;
}

void printQueue(Queue *q) {
	TQNode *e;
	e = q->front;

	if (!e) {
		cout << "此队列为空!" << endl;
		return;
	}

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

void task1() {
	cout << "进行了第一个工作" << endl;
}

void task2() {
	cout << "进行了第二个工作" << endl;
}

int main(void) {
	Queue *q;

	if (!initQueue(q)) {
		cout << "队列初始化失败!" << endl;
		return 0;
	}

	TQNode *task=new TQNode;
	task->id = 0;
	task->handle = &task1;
	task->next = NULL;

	insertQueue(q, task);

	TQNode *_task = new TQNode;
	_task->id = 1;
	_task->handle = &task2;
	_task->next = NULL;

	insertQueue(q, _task);
	cout << "待完成的任务编号:";
	printQueue(q);

	while (task = deleteQueue(q)) {
		task->handle();
		delete task;
	}
	cout << "待完成的任务编号:";
	printQueue(q);
	delete q;

	system("pause");
	return 0;
}

任务队列_第2张图片

你可能感兴趣的:(数据结构,C++,任务队列)