一、队列的概念
队列是一种特殊的线性表,严格按照“先进先出”的原则。
二、队列基础
队列和栈一样只允许在断点处插入和删除元素,其基本操作包括以下:
(1)InitQueue(&Q); //初始化一个空队列
(2)DestroyQueue(&Q); //清空队列
(3)QueueEmpty(&Q); //队列判空
(4)QueueLength(&Q); //求队列的长度
(5)GetHead(Q,&e); //取对头元素
(6)EnQueue(&Q,e); //插入新元素
(7)DeQueue(&Q,&e); //删除队头元素
(8)QueueTraverse(Q,visit()); //每个元素调用visit()函数
队列的分类:链队列和循环队列
C语言定义链队的格式
typedef structQNode
{
ElemType data;struct Qnode *next;
}QNode,*QueuePtr;
typedefstruct{
QueuePtr front;//对头指针,指向头元素
QueuePtr rear; //队尾指针,指向队尾元素
}LinkQueue;
可以采用顺序表来存储定义循环队列,具体代码如下:
#define MAXQSIZE 100 //最长队列长度typedefstruct{
ElemType*base; //存储空间
int front; //头指针,指向队列的头元素
int rear; //尾指针,指向队列元素的下一个位置
}SqQueue;
队列的基本操作
(1)初始化队列Q的目的是创建一个队列
void InitQueue(QUEUE *Q)
{
Q->front = -1;
Q->rear = -1;
}
(2)入队的目的是将一个新元素添加到队尾,相当于队列最后队列等候。
void EnQueue(QUEUE *Q, Elemtype elem){if ((Q->rear+1)%MAX_QUEUE==Q->front)
{
exit(OVERFLOW);
}else{
Q->rear = (Q->reasr + 1) %MAX_QUEUE;
Q->elem[Q->rear] =elem;
}
}
(3)出队的目的是取出对头元素,并同时删除该元素,使后一个元素成为对头元素。
void DeQueue(QUEUE *Q, Elemtype *elem)
{if (QueueEmpty(*Q))
{
exit("Queue is empty.");
}else{
Q->front = (Q->front + 1) %MAX_QUEUE;*elem = Q->elem[Q->front];
}
}
(4)获取队列的第一个元素,即将队头的元素取出,不删除该元素,队头仍然是该元素。
void GetFront(QUEUE *Q, Elemtype *elem)
{if (QueueEmpty(*Q))
{
exit("Queue is empty.");
}else{*elem = Q->elem[ (Q->front + 1) %MAX_QUEUE];
}
}
(5)判断队列Q是否为空
intQueueEmpty(Queue Q)
{if (Q.front==Q.rear)
{returnTRUE;
}else{returnFALSE;
}
}
队列的链式存储
在C语言中,链式队列的基本操作算法如下:
(1)初始化队列Q,算法代码如下:
void InitQueue(QUEUE *Q)
{
Q->front = (LINKLIST*)malloc(sizeof(LINKLIST));if (Q->front==NULL)
{
exit(ERROR);
}
Q->rear = Q->front;
}
(2)入队操作
void EnQueue(QUEUE *Q, Elemtype elem){
s= (LINKLIST*)malloc(sizeof(LINKLIST));if (!s)
{
exit(ERROR);
}
s->elem =elem;
s->next =NULL;
Q->rear->next =s;
Q->rear =s;
}
(3)出队操作
void DeQueue(QUEUE *Q, Elemtype *elem)
{if (QueueEmpty(*Q))
{
exit(ERROR);
}else{*elem = Q->front->next->elem;
s= Q->front->next;
Q->front->next = s->next;
Q->front = (Q->front + 1) %MAX_QUEUE;free(s);
}
}
(4)获取队头元素
void GetFront(QUEUE Q, Elemtype *elem)
{if(QueueEmpty(Q))
{
exit(ERROR);
}else{*elem = Q->front->next->elem;
}
}
(5)判断队列Q是否为空
voidQueueEmpty(QUEUE Q)
{if (Q->front==Q->rear)
{returnTRUE;
}else{returnFALSE;
}
}
三、实例演练
“新增顾客”编号问题
代码实现:
/*构建一个完整循环队列*/#include"stdio.h"#include"malloc.h"
#define QUEUEMAX 15
//typedef DATA;
typedef struct{
DATA data[QUEUEMAX];//队列数组
inthead;inttail;
}CycQueue;
CycQueue*CycQueueInit()
{
CycQueue*q;if (q=(CycQueue *)malloc(sizeof(CycQueue)))
{
q->head = 0;//设置队头
q->tail = 0;//设置队尾
returnq;
}else{return NULL;//返回空
}
}void CycQueueFree(CycQueue *q) //释放队列
{if (q!=NULL)free(q);
}int CycQueueIsEmpty(CycQueue *q) //队列是否为空
{return (q->head == q->tail);
}int CycQueueIsFull(CycQueue *q) //队列是否为满
{return ((q->tail + 1) % QUEUEMAX == q->head);
}int CycQueueIn(CycQueue *q, DATA data) //入队
{if ((q->tail + 1) % QUEUEMAX == q->head)
{
printf("队列满了!");return 0;
}else{
q->tail = (q->tail + 1) % QUEUEMAX;//求列尾序号
q->data[q->tail] =data;return 1;
}
}
DATA*CycQueueOut(CycQueue *q) //循环队列出队函数
{if (q->head==q->tail) //队列为空
{
printf("队列为空了!");returnNULL;
}else{
q->head = (q->head + 1) %QUEUEMAX;return &(q->data[q->head]);
}
}int CycQueueLen(CycQueue *q) //获取队列长度
{intn;
n= q->tail - q->head;if (n<0)
{
n= QUEUEMAX +n;
}returnn;
}
DATA*CycQueuePeek(CycQueue *q) //获取队列第一个位置的数据
{if (q->head==q->tail)
{
printf("队列已经空了!");returnNULL;
}else{return &(q->data[(q->head + 1) %QUEUEMAX]);
}
}
##############################################
#include"stdlib.h"#include"stdio.h"#include"time.h"#include"xuncao.h"typedefstruct{int num; //顾客编号
long time; //进入队列的时间
}DATA;int num; //顾客序号
void add(CycQueue *q) //新增顾客排列
{
DATA data;if (!CycQueueIsFull(q))
{
data.num= ++num;
data.time=time(NULL);
CycQueueIn(q, data);
}else{
printf("排队的人实在是太多了,请您稍候再排队!");
}
}void next(CycQueue *q) //通知下一位顾客准备
{
DATA*data;if (!CycQueueIsEmpty(q)) //若队列不为空
{
data= CycQueueOut(q); //取队列头部的数据
printf("欢迎编号为%d的顾客到柜台办理业务!", data->num);
}if (!CycQueueIsEmpty(q)) //若队列不为空
{
data= CycQueuePeek(q); //取队列中指定位置的数据
printf("请编号为%d的顾客做好准备,马上将为您办理业务!", data->num);
}
}intmain()
{
CycQueue*queuel;inti, n;char select;
num= 0; //顾客序号
queuel = CycQueueInit();//初始化队列
if (queuel==NULL)
{
printf("创建队列时出错误!");
getch();return 0;
}do{
printf("请选择具体操作:");
printf("1.新到顾客");
printf("2.下一个顾客");
printf("0.退出");
fflush(stdin);select =getch();switch (select)
{case'1':
add(queuel);
printf("现在共有%d位顾客在等候!", CycQueueLen(queuel));break;case'2':
next(queuel);
printf("现在共有%d位顾客在等候!", CycQueueLen(queuel));break;case'0':break;
}
}while (select!='0');
CycQueueFree(queuel);//释放队列
system("pause");return 0;
}
代码实现