目录
一、队列的定义
队列是限制在两端进行插入操作和删除操作的线性表
允许进行存入操作的一端称为“队尾”
允许进行删除操作的一端称为“队头”
当线性表中没有元素时,称为“空队”
特点 :先进先出(FIFO)
有个浪费一个的思想,是浪费对头还是对尾,看情况,顺序队列浪费对尾、链式队列浪费对头
二、双端队列
双端队列(Deque)是指允许两端都可以进行入和出队操作的队列,deque 是 “double ended queue” 的简称。那就说明元素可以从队头出队和入队,也可以从队尾出队和入队。
固定一端其实就能当栈来使用。
三、队列的应用场景
1、通讯应用,先进来的会先收到消息
2、访问旅游城市规划。
B城市先访问,B城市的孩子城市也会先访问,这就是先进先出的思想。
四、队列的实现
front指向对头元素的位置。
rear指向对尾元素的下一个位置。
在队列操作过程中,为了提高效率,以调整指针代替队列元素的移动,并将数组作为循环队列的操作空间。
为区别空队和满队,满队元素个数比数组元素个数少一个。
1、队列结构和相应的头文件
sequeue.h
typedef int datatype;
#define N 128 //队列容量
typedef struct {
datatype data[N]; //用数组作为队列的存储空间
int front; //指示队头
int rear; //指示对尾
}sequeue;
sequeue * queue_create();
int enqueue(sequeue *sq, datatype x);
datatype dequeue(sequeue *sq);
int queue_empty(sequeue *sq);
int queue_full(sequeue *sq);
int queue_clear(sequeue *sq);
sequeue * queue_free(sequeue *sq);
2、创建队列
sequeue * queue_create() {
sequeue *sq;
if ((sq = (sequeue *)malloc(sizeof(sequeue))) == NULL) {
printf("malloc failed\n");
return NULL;
}
memset(sq->data, 0, sizeof(sq->data));
sq->front = sq->rear = 0;
return sq;
}
3、入队
int enqueue(sequeue *sq, datatype x) {
if (sq == NULL) {
printf("sq is NULL\n");
return -1;
}
if ((sq->rear + 1) % N == sq->front) {
printf("sequeue is full\n");
return -1;
}
sq->data[sq->rear] = x;
sq->rear = (sq->rear + 1) % N;
return 0;
}
4、出队
datatype dequeue(sequeue *sq) {
datatype ret;
ret = sq->data[sq->front];
sq->front = (sq->front + 1) % N;
return ret;
}
5、判断队列是否满
int queue_full(sequeue *sq) {
if (sq == NULL) {
printf("sq is NULL\n");
return -1;
}
if ((sq->rear + 1) % N == sq->front) {
return 1;
}
else {
return 0;
}
}
6、判断队列空
int queue_empty(sequeue *sq) {
if (sq == NULL) {
printf("sq is NULL\n");
return -1;
}
return (sq->front == sq->rear ? 1 : 0);
}
7、 清空队列
int queue_clear(sequeue *sq) {
if (sq == NULL) {
printf("sq is NULL\n");
return -1;
}
sq->front = sq->rear = 0;
return 0;
}
8、释放队列
sequeue * queue_free(sequeue *sq) {
if (sq == NULL) {
printf("sq is NULL\n");
return NULL;
}
free(sq);
sq = NULL;
return NULL;
}
9、主函数main.c用于测试
#include <stdio.h>
#include "sequeue.h"
int main(int argc, const char *argv[])
{
sequeue *sq;
if ((sq = queue_create()) == NULL) {
return -1;
}
enqueue(sq, 10);
enqueue(sq, 100);
enqueue(sq, 1000);
while (!queue_empty(sq)) {
printf("dequeue:%d\n", dequeue(sq));
}
queue_free(sq);
return 0;
}
五、链式队列
插入操作在队尾进行,删除操作在队头进行,由队头指针和队尾指针控制队列的操作。
linkstack.h文件
typedef int data_t;
typedef struct node {
data_t data;
struct node *next;
}listnode, *linkstack;
linkstack stack_create();
int stack_push(linkstack s, data_t value);
data_t stack_pop(linkstack s);
int stack_empty(linkstack s);
data_t stack_top(linkstack s);
linkstack stack_free(linkstack s);
linkstack.c文件
#include <stdio.h>
#include <stdlib.h>
#include "linkqueue.h"
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;
}
int enqueue(linkqueue *lq, datatype x) {
linklist p;
if (lq == NULL) {
printf("lq is NULL\n");
return -1;
}
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;
}
datatype dequeue(linkqueue *lq) {
linklist p;
if (lq == NULL) {
printf("lq is NULL\n");
return -1;
}
p = lq->front;
lq->front = p->next;
free(p);
p = NULL;
return (lq->front->data);
}
int queue_empty(linkqueue *lq) {
if (lq == NULL) {
printf("lq is NULL\n");
return -1;
}
return (lq->front == lq->rear ? 1 : 0);
}
int queue_clear(linkqueue *lq) {
linklist p;
if (lq == NULL) {
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;
}
linkqueue * queue_free(linkqueue *lq) {
linklist p;
if (lq == NULL) {
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;
}
main.c测试函数
#include <stdio.h>
#include "linkqueue.h"
int main(int argc, const char *argv[])
{
linkqueue *lq;
lq = queue_create();
if (lq == NULL)
return -1;
enqueue(lq, 10);
enqueue(lq, 20);
enqueue(lq, 30);
enqueue(lq, 40);
//while (!queue_empty(lq)) {
//printf("dequeue:%d\n", dequeue(lq));
//}
queue_clear(lq);
lq = queue_free(lq);
enqueue(lq, 50);
return 0;
}
六、队列的应用球钟问题
球钟是一个利用球的移动来记录时间的简单装置 它有三个可以容纳若干个球的指示器:分钟指示器,五分钟指示器,小时指示器 若分钟指示器中有2个球,五分钟指示器中有6个球,小时指示器中有5个球,则时间为5:32
每过一分钟,球钟就会从球队列的队首取出一个球放入分钟指示器,分钟指示器最多可容纳4个球。 当放入第五个球时,在分钟指示器的4个球就会按照他们被放入时的相反顺序加入球队列的队尾。而第五个球就会进入五分钟指示器。 按此类推,五分钟指示器最多可放11个球,小时指示器最多可放11个球。
当小时指示器放入第12个球时,原来的11个球按照他们被放入时的相反顺序加入球队列的队尾,然后第12个球也回到队尾。这时,三个指示器均为空,回到初始状态,从而形成一个循环。因此,该球钟表示时间的范围是从0:00到11:59。 现设初始时球队列的球数为27,球钟的三个指示器初态均为空。问,要经过多久,球队列才能回复到原来的顺序?
linkqueue.h
typedef int datatype;
typedef struct node {
datatype data;
struct node *next;
}listnode , *linklist;
typedef struct {
linklist front;
linklist rear;
}linkqueue;
linkqueue * queue_create();
int enqueue(linkqueue *lq, datatype x);
datatype dequeue(linkqueue *lq);
int queue_empty(linkqueue *lq);
int queue_clear(linkqueue *lq);
linkqueue * queue_free(linkqueue *lq);
linkqueue.c
#include <stdio.h>
#include <stdlib.h>
#include "linkqueue.h"
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;
}
int enqueue(linkqueue *lq, datatype x) {
linklist p;
if (lq == NULL) {
printf("lq is NULL\n");
return -1;
}
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;
}
datatype dequeue(linkqueue *lq) {
linklist p;
if (lq == NULL) {
printf("lq is NULL\n");
return -1;
}
p = lq->front;
lq->front = p->next;
free(p);
p = NULL;
return (lq->front->data);
}
int queue_empty(linkqueue *lq) {
if (lq == NULL) {
printf("lq is NULL\n");
return -1;
}
return (lq->front == lq->rear ? 1 : 0);
}
int queue_clear(linkqueue *lq) {
linklist p;
if (lq == NULL) {
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;
}
linkqueue * queue_free(linkqueue *lq) {
linklist p;
if (lq == NULL) {
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;
}
sqstack.h
typedef int data_t;
typedef struct {
data_t *data;
int maxlen;
int top;
}sqstack;
sqstack * stack_create(int len);
int stack_push(sqstack * s, data_t value);
int stack_empty(sqstack *s);
int stack_full(sqstack *s);
data_t stack_pop(sqstack *s);
data_t stack_top(sqstack *s);
int stack_clear(sqstack *s);
int stack_free(sqstack *s);
sqstack.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sqstack.h"
sqstack * stack_create(int len) {
sqstack * s;
if ((s =(sqstack *)malloc(sizeof(sqstack))) == NULL) {
printf("malloc sqstack failed\n");
return NULL;
}
if ((s->data = (data_t *)malloc(len * sizeof(data_t)))==NULL) {
printf("malloc data failed\n");
free(s);
return NULL;
}
memset(s->data, 0, len*sizeof(data_t));
s->maxlen = len;
s->top = -1;
return s;
}
int stack_push(sqstack * s, data_t value) {
if (s == NULL) {
printf("s is NULL\n");
return -1;
}
if (s->top == s->maxlen-1) {
printf("stack is full\n");
return -1;
}
s->top++;
s->data[s->top] = value;
return 0;
}
/*
*@ret 1-empty
* */
int stack_empty(sqstack *s) {
if (s == NULL) {
printf("s is NULL\n");
return -1;
}
return (s->top == -1 ? 1 : 0);
}
/*
* @ret 1-full
* */
int stack_full(sqstack *s) {
if (s == NULL) {
printf("s is NULL\n");
return -1;
}
return (s->top == s->maxlen-1 ? 1 : 0);
}
data_t stack_pop(sqstack *s) {
s->top--;
return (s->data[s->top+1]);
}
data_t stack_top(sqstack *s) {
return (s->data[s->top]);
}
int stack_clear(sqstack *s) {
if (s == NULL) {
printf("s is NULL\n");
return -1;
}
s->top = -1;
return 0;
}
int stack_free(sqstack *s) {
if (s == NULL) {
printf("s is NULL\n");
return -1;
}
if (s->data != NULL)
free(s->data);
free(s);
return 0;
}
test.c
#include <stdio.h>
#include "linkqueue.h"
#include "sqstack.h"
int check(linkqueue * lq);
int main(int argc, const char *argv[])
{
linkqueue *lq;
sqstack *s_hour, *s_five, *s_min;
int value;
int i, min = 0;
if ((lq = queue_create()) == NULL) {
return -1;
}
for (i = 1; i <= 27; i++) {
enqueue(lq, i);
}
if ((s_hour = stack_create(11)) == NULL) {
return -1;
}
if ((s_five = stack_create(11)) == NULL) {
return -1;
}
if ((s_min = stack_create(4)) == NULL) {
return -1;
}
while (1) {
min++;
if (!queue_empty(lq)) {
value = dequeue(lq);
if (!stack_full(s_min)) {
stack_push(s_min, value);
} else {
while (!stack_empty(s_min)) {
enqueue(lq, stack_pop(s_min));
}
if (!stack_full(s_five)) {
stack_push(s_five, value);
} else {
while (!stack_empty(s_five)) {
enqueue(lq, stack_pop(s_five));
}
if (!stack_full(s_hour)) {
stack_push(s_hour, value);
} else {
while (!stack_empty(s_hour)) {
enqueue(lq, stack_pop(s_hour));
}
enqueue(lq, value);
//0:0
if (check(lq) == 1) {
break;
}
}
}
}
}
}
printf("total:%d\n", min);
printf("dequeue:");
while (!queue_empty(lq))
printf("%d ", dequeue(lq));
puts("");
return 0;
}
int check(linkqueue * lq) {
linklist p;
if (lq == NULL) {
printf("lq is NULL\n");
return -1;
}
p = lq->front->next;
while (p && p->next) {
if (p->data < p->next->data) {
p = p->next;
} else {
return 0;
}
}
return 1;
}