一、顺序队列的原理
1.1 顺序队列
队列: 队列是一种特殊的线性表,其特点是在其两端进行插入和删除操作受到限制,只允许在一端(称为队尾)进行插入,而在另一端(称为队头)进行删除。
①允许进行存入操作的一端称为“队尾”。
②允许进行删除操作的一端称为“队头”。
③当线性表中没有元素时,称为“空队”。
特点: 先进先出(FIFO)
-
规定:front指向队头元素的位置; rear指向队尾元素的下一个位置。
-
在队列操作过程中,为了提高效率,以调整指针代替队列元素的移动,并将数组作为循环队列的操作空间。
-
为区别空队和满队,满队元素个数比数组元素个数少一个。
1.2 应用
1、计算机系统:用于CPU的作业调度、图遍历的广度优先查找等。
2、消息传递:在生产环境中,多个进程或多个应用程序之间需要高效地传递消息,以协调任务的执行,这时可以使用队列作为消息传递的媒介,实现消息的异步传递和处理。
二、顺序队列的实现
2.1 结构体创建
typedef int datatype; //定义队列中数据元素的数据类型
#define N 128 //定义队列的容量
typedef struct{
datatype data[N]; //用数组作为队列的储存空间
int front, rear; //指示队头位置和队尾位置的指针
} sequeue; //顺序队列类型定义
2.2 队列的创建
算法思路:
①申请内存。
②初始化。
sequeue * queue_creat()
{
sequeue *sq;
if((sq = (sequeue *)malloc(sizeof(sequeue))) == NULL)
{
printf("malloc failed\n");
return NULL;
}
memset(sq->data, 0, sizeof(data));
sq->front = sq->rear = 0;
return sq;
}
2.3 入队
算法思路:
为了防止rear溢出,这里采用取余循环(rear + 1) % N,这样当到127是,又回到了0。
①判断队列是否满?
②存值,rear++;
int enqueue(sequeue *sq, datatype x)
{
if((sq->rear + 1) % N == front)
{
printf("sq is full\n");
return -1;
}
sq->data[sq->rear] = x;
sq->rear = (sq->rear + 1) % N;
return 0;
}
2.4 出队
算法思路:
①判断队列是否空?
②front++.
datatype dequeue(sequeue *sq){
if(NULL == sq){
printf("sequeue is NULL\n");
return -1;
}
if(sq->rear == sq->front){
printf("sequeue is empty!\n");
return -1;
}
datatype ret = sq->data[sq->front];
sq->front = (sq->front + 1) % N;
return ret;
}
2.5 判断队列是否空
int queue_empty(sequeue *sq){
if(NULL == sq){
printf("sequeue is NULL\n");
return -1;
}
return (sq->front == sq->rear ? 1 : 0);
}
2.6 判断队列是否满
int queue_full(sequeue *sq){
if(NULL == sq){
printf("sequeue is NULL\n");
return -1;
}
if((sq->rear + 1) % N == sq->front){
return 1;
}
else{
return 0i;
}
}
2.7 清空队列
int queue_clear(sequeue *sq){
if(NULL == sq){
printf("sequeue is NULL\n");
return -1;
}
sq->front = sq->rear = 0;
return 0;
}
2.8 释放队列
sequeue *queue_free(sequeue *sq){
if(NULL == sq){
printf("sequeue is NULL\n");
return NULL;
}
free(sq);
sq = NULL;
return NULL;
}
三、链式队列的原理
3.1链式队列
插入操作在队尾进行,删除操作在队头进行,由队头指针和队尾指针控制队列的操作。
3.2 应用
- 网络请求队列: 在网络请求中,可以使用链式队列来管理请求的顺序。每个请求都可以以节点的形式加入队列,然后按照先进先出的原则依次处理请求。
- 任务调度队列: 在多线程任务调度中,可以使用链式队列来管理待执行的任务。每个任务都可以以节点的形式加入队列,并按照一定的优先级规则进行调度。
- 缓存队列: 在缓存中,可以使用链式队列来管理缓存的数据。每个数据可以以节点的形式加入队列,然后按照一定的容量规则进行淘汰。
- UI消息队列: 在图形界面开发中,可以使用链式队列来管理UI的更新消息。每个消息都可以以节点的形式加入队列,然后按照先进先出的原则进行处理,保证UI的更新是有序的。
- 日志队列: 在日志系统中,可以使用链式队列来管理日志的写入和读取。每条日志可以以节点的形式加入队列,然后按照先进先出的原则进行写入和读取,保证日志的顺序性。
四、链式队列的实现
3.1 结构体创建
typedef int datatype;
// 定义链表节点结构体
typedef struct node {
datatype data; // 节点数据
struct node *next; // 指向下一个节点的指针
} listnode, *linklist; // listnode为节点类型,linklist为指向节点的指针类型
// 定义链式队列结构体
typedef struct {
linklist front, rear; // 队列的前端和后端指针
} linkqueue;
3.2 队列的创建
算法思路:
①申请内存。
②初始化。
③返回值。
linkqueue *queue_create(){
linkqueue *lq;
if((lq = (linkqueue *)malloc(sizeof(linkqueue))) == NULL){
printf("malloc linkqueue failed\n");
return NULL;
}
lq->front = lq->rear = (linklist)malloc(sizeof(listnode));
if(lq->front == NULL){
printf("malloc node failed\n");
return NULL;
}
lq->front->data = 0;
lq->front->next = NULL;
return lq;
}
3.3 入队
int enqueue(linkqueue *lq, datatype x){
if(NULL == lq){
printf("lq is NULL\n");
return -1;
}
linklist p;
if((p = (linklist)malloc(sizeof(listnode))) == NULL){
printf("malloc node failed\n");
return -1;
}
p->data = x;
p->next = NULL;
lq->rear->next = p;
lq->rear = p;
return 0;
}
3.4 出队
datatype dequeue(linkqueue *lq){
linklist p;
if(NULL == lq){
printf("lq is NULL\n");
return -1;
}
p = lq->front;
lq->front = p->next;
free(p);
p = NULL;
return lq->front->data;
}
3.5 判断队列是否空
int queue_empty(linkqueue *lq){
if(NULL == lq){
printf("lq is NULL\n");
return -1;
}
return (lq->front == lq->rear ? 1 : 0);
}
3.6 清除队列
int queue_clear(linkqueue *lq){
linklist p;
if(NULL == lq){
printf("lq is NULL\n");
return -1;
}
while(lq->front->next){
p = lq->front;
lq->front = p->next;
printf("clear free:%d\n", p->data);
free(p);
p = NULL;
}
return 0;
}
3.7 释放队列
linkqueue * queue_release(linkqueue *lq){
linklist p;
if(NULL == lq){
printf("lq is NULL\n");
return NULL;
}
while(lq->front){
p = lq->front;
lq->front = p->next;
printf("free:%d\n", p->data);
free(p);
}
free(lq);
lq = NULL;
return NULL;
}