一、什么是队列
说到队列我们可能会想到现实世界的排队情况,其实队列这种线性表的结构和现实的队列有着很相似的地方,首先我们在排队的时候只能在队尾进行人员的插入,而我们人员在出去的时候只能是在队头,这就有着一个先进先出的原则,那么回到队列,他也是一种操作受限的线性表,只允许在表的一端插入,而在另一端删除,符合前面所说的先进先出原则。其中这个结构中队头和队尾两个指针,队头是允许出队的一端,队尾是允许插入的一端。
要实现队列的基本操作:
InitQueue(&Q):初始化队列,构造一个空队列
QueueEmpty(&Q):判断队列是否为空
EnQueue(&Q,x):入队,若队列未满,将x插入,使其称为新的队尾
DeQueue(&Q,&x):出队,若队列非空,删除队头元素并用x返回
GetHead(Q,&x):若队列非空获取队头元素由x返回
二、顺序队列的基本结构以及操作
结构:
#define MaxSize 100 typedef struct { ElemType data[MaxSize]; int front, rear; //队头以及队尾指针 }SeqQueue;
基本操作:
seqQueue.h
#include<stdio.h> #define MaxSize 100 #define True 1 #define False 0 typedef int ElemType; typedef int Status; typedef int Boolean; typedef struct { ElemType data[MaxSize]; int front, rear; //队头以及队尾指针 }SeqQueue; void InitSeqQueue(SeqQueue *Q);//初始化队列,构造一个空队列 Boolean SeqQueueEmpty(SeqQueue Q);//判断队列是否为空 Status EnSeqQueue(SeqQueue *Q,ElemType x);//入队,若队列未满,将x插入,使其称为新的队尾 Status DeSeqQueue(SeqQueue *Q, ElemType *x);//出队,若队列非空,删除队头元素并用x返回 Status GetSeqQueueHead(SeqQueue Q,ElemType *x);//若队列非空获取队头元素由x返回
seqQueue.c
#include"seqQueue.h" void InitSeqQueue(SeqQueue *Q) { //初始化队列,构造一个空队列 Q->front = 0; Q->rear = 0; } Status EnSeqQueue(SeqQueue *Q, ElemType x) { //入队,若队列未满,将x插入,使其称为新的队尾 if (Q->rear == MaxSize) return 0; Q->data[Q->rear] = x; Q->rear++; return 1; } Status DeSeqQueue(SeqQueue *Q, ElemType *x) { //出队,若队列非空,删除队头元素并用x返回 if (Q->rear == MaxSize) return 0; *x = Q->data[Q->front]; Q->front++; return 1; } Boolean SeqQueueEmpty(SeqQueue Q) { //判断队列是否为空 if (Q.front == Q.rear) return True; else return False; } Status GetSeqQueueHead(SeqQueue Q, ElemType *x) { //若队列非空获取队头元素由x返回 if (Q.front == MaxSize) return 0; *x = Q.data[Q.front]; return 1; }
三、循环队列
在下图这种情况下的队列,在队列进行是否满的判断下,队列中只有一个元素,但是符合队列满的条件,这是一种假的溢出,所以为了解决这个问题,我们引入了循环队列。
循环队列是我们认为把队列想象为一个环状,当队列的头指针为MaxSize-1后我们再前进一个位置就自动归0,所以我们可以用取余运算(%)来完成
初始时:头指针等于尾指针等于0
出队时:Q.front = (Q.front+1)%Maxsize
入队时:Q.rear = (Q.rear+1)%MaxSize
循环队列结构:
#define MaxSize 100 typedef struct { ElemType data[MaxSize]; int front, rear; //队头以及队尾指针 int tag; //用来区分队空还是队满的标志量 }CycleSeqQueue;
循环队列的操作:
cycleSeqQueue.h
#include<stdio.h> #define MaxSize 100 #define True 1 #define False 0 typedef int ElemType; typedef int Status; typedef int Boolean; typedef struct { ElemType data[MaxSize]; int front, rear; //队头以及队尾指针 int tag; //用来区分队空还是队满的标志量 }CycleSeqQueue; void InitCycleSeqQueue(CycleSeqQueue *Q);//初始化队列,构造一个空队列 Boolean CycleSeqQueueEmpty(CycleSeqQueue Q);//判断队列是否为空 Status EnCycleSeqQueue(CycleSeqQueue *Q, ElemType x);//入队,若队列未满,将x插入,使其称为新的队尾 Status DeCycleSeqQueue(CycleSeqQueue *Q, ElemType *x);//出队,若队列非空,删除队头元素并用x返回 Status GetCycleSeqQueueHead(CycleSeqQueue Q, ElemType *x);//若队列非空获取队头元素由x返回
cycleSeqQueue.c
#include"cycleSeqQueue.h" void InitCycleSeqQueue(CycleSeqQueue *Q) { //初始化队列,构造一个空队列 Q->front = 0; Q->rear = 0; Q->tag = 1; //默认为1当入队时变为0出队时变为1 } Status EnCycleSeqQueue(CycleSeqQueue *Q, ElemType x) { //入队,若队列未满,将x插入,使其称为新的队尾 if (Q->tag == 0 && Q->front == Q->rear) return 0; Q->data[Q->rear] = x; Q->rear = (Q->rear + 1) % MaxSize; Q->tag = 1; return 1; } Status DeCycleSeqQueue(CycleSeqQueue *Q, ElemType *x) { //出队,若队列非空,删除队头元素并用x返回 if (Q->tag == 1 && Q->front == Q->rear) return 0; *x = Q->data[Q->front]; Q->front = (Q->front + 1) % MaxSize; Q->tag = 0; return 1; } Boolean CycleSeqQueueEmpty(CycleSeqQueue Q) { //判断队列是否为空 if (Q.tag == 0 && Q.front == Q.rear) return True; return False; } Status GetCycleSeqQueueHead(CycleSeqQueue Q, ElemType *x) { //若队列非空获取队头元素由x返回 if (Q.tag == 0 && Q.front == Q.rear) return 0; *x = Q.data[Q.front]; return 1; }
四、队列的链式存储结构
链式存储结构的队列时由两部分组成,一个时队列本身的结构和头指针与尾指针组成的单链表结构:
链式存储类型的结构:
typedef struct { //节点结构体 ElemType data; LinkQueueNode *next; }LinkQueueNode; typedef struct { //队列结构体 LinkQueueNode *front, *rear; }LinkQueue;
链式存储结构的基本操作:
LinkQueue.h
#include<stdio.h> #define MaxSize 100 #define True 1 #define False 0 typedef int ElemType; typedef int Status; typedef int Boolean; typedef struct { //节点结构体 ElemType data; LinkQueueNode *next; }LinkQueueNode; typedef struct { //队列结构体 LinkQueueNode *front, *rear; }LinkQueue; void InitLinkQueue(LinkQueue *Q);//初始化链式循环队列 Boolean LinkQueueEmpty(LinkQueue Q);//判断队列是否为空 Status EnLinkQueue(LinkQueue *Q, ElemType x);//入队,将x插入,使其称为新的队尾 Status DeLinkQueue(LinkQueue *Q, ElemType *x);//出队,若队列非空,删除队头元素并用x返回 Status GetLinkQueueHead(LinkQueue Q, ElemType *x);//若队列非空获取队头元素由x返回
linkQueue.c
#include"linkQueue.h" void InitLinkQueue(LinkQueue *Q) { //初始化链式循环队列 LinkQueueNode *N= (LinkQueueNode*)malloc(sizeof(LinkQueueNode)); Q->front = N; Q->rear = N; Q->front->next = NULL; Q->rear->next = NULL; } Boolean LinkQueueEmpty(LinkQueue Q) { //判断队列是否为空 if (Q.front == Q.rear) return True; return False; } Status EnLinkQueue(LinkQueue *Q, ElemType x) { //入队,将x插入,使其称为新的队尾 LinkQueueNode *newSpace = (LinkQueueNode*)malloc(sizeof(LinkQueueNode)); newSpace->data = x; newSpace->next = NULL; Q->rear->next = newSpace; Q->rear = newSpace; return 1; } Status DeLinkQueue(LinkQueue *Q, ElemType *x) { //出队,若队列非空,删除队头元素并用x返回 if (Q->front == Q->rear) return 0; LinkQueueNode *p = Q->front->next; *x = p->data; Q->front->next = p->next; if (Q->rear == p) Q->rear = Q->front; free(p); return True; }