利用静态队列实现订餐取餐系统
如题。题主在一次吃肯德基的时候看到餐厅里的订餐取餐系统,突发奇想。联想到最近学习的队列的相关知识,准备动手用静态队列实现一个类似于现代餐厅的订餐取餐系统。由于题主没有学习过c语言,仅仅学习过数据结构的一点皮毛,在此恳请各位大牛不吝赐教。
订餐取餐系统属于典型的“先进先出”的线性表。所以自然而然会想到到利用队列来实现。第一次由于队列及其相关功能实现出现问题,导致这一想法不了了之。就在这个正月初一的早上,题主闲着蛋疼,又一次想到了这个程序。于是在论坛上找到了一位前辈编写的静态队列的相关实现,照搬了过来,这么一试果然成功了(不得不说王道书上的不少代码压根跑不起来)。
设计本身并没有什么难度。取餐就在队头出队,订餐就在队尾入队。唯一的问题是,取餐码该如何实现?我设想了两种方案,一种是回收取餐码的,预设大量的取餐码,订餐就从出餐队列中弹出一个取餐码,取餐就把相对应的取餐码入队回收。但是这种算法需要设定三个队列,分别是:
出餐队列——用以存放预设的取餐码,每出现一次订餐操作就从中弹出一个;
等候队列——弹出的取餐码进入等候队列,出现出餐操作的时候就把队头元素出队;
回收队列——出队的取餐码进入到回收队列中,回收队列的队头元素每次循环出队一个,进入到出餐队列中。
但实际操作中这种算法空间复杂度较高,而且每天的用餐人数实际上并不固定,如果设定过多的取餐码会造成内存的浪费,因此我想到了第二种方案。
第二种方案就是不回收取餐码。在一个while循环外部定义一个整型变量Num,设初值为1。在循环内部对这个整型变量自加。伴随着while循环的进行,这个整型变量会形成一个递增的顺序序列。这样只需要定义一个等候队列即可。如果switch开关选择的是取餐操作,Num还是会+1,但不对这个变量进行任何操作;如果switch开关选择是订餐操作,则会直接将这个Num值入队,相当于临时分配了一个取餐码。这种实现方式有一个问题,即:如果一次循环没有进行订餐操作,Num值还是会+1,取餐码有可能跳过部分的顺序序列。但这个问题实际上是无足轻重的,因为取餐码的关键并不是是否顺序,而是一段时间内不会出现冲突,这种方式很明显能够避免冲突且不会造成资源的浪费。
以下是代码:
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
#include <stdbool.h>
#define MaxSize 51 //宏定义,设定队列的长度为MaxSize-1
typedef struct Queue {
int* pBase;
int front;
int rear;
}QUEUE, * PQUEUE; //定义队列PQUEUE
void init(PQUEUE); //初始化队列
bool en_queue(PQUEUE, int); //入队
bool out_queue(PQUEUE, int*); //出队
bool is_empty(PQUEUE); //判断队空
bool is_full(PQUEUE); //判断队满
void traverse(PQUEUE); //遍历队列
void init(PQUEUE pQ) {
pQ->pBase = (int*)malloc(sizeof(int) * MaxSize);
if (NULL == pQ->pBase) {
printf("内存分配失败,程序退出!\n");
exit(-1);
}
pQ->front = 0;
pQ->rear = 0;
return;
}
bool en_queue(PQUEUE pQ, int val) {
if (is_full(pQ)) {
return false;
}
pQ->pBase[pQ->rear] = val;
pQ->rear = (pQ->rear + 1) % MaxSize;
return true;
}
bool out_queue(PQUEUE pQ, int* pVal) {
if (is_empty(pQ)) {
return false;
}
*pVal = pQ->pBase[pQ->front];
pQ->front = (pQ->front + 1) % MaxSize;
return true;
}
bool is_empty(PQUEUE pQ) {
if (pQ->front == pQ->rear) {
return true;
}
else {
return false;
}
}
bool is_full(PQUEUE pQ) {
if ((pQ->rear + 1) % MaxSize == pQ->front) {
return true;
}
else {
return false;
}
}
void traverse(PQUEUE pQ) {
printf("遍历队列: ");
int cnt = pQ->front;
while (cnt != pQ->rear) {
printf("%d ", pQ->pBase[cnt]);
cnt = (cnt + 1) % MaxSize;
}
printf("\n");
}
int main(int argc, const char* argv[]) {
int Open;
printf("***开机请输入“1”***\n");
printf("***调试请输入“0”***\n");
scanf_s("%d", &Open);
printf("\n");
if (Open == 1) {
printf("正在初始化,请稍后……\n");
QUEUE Q;
init(&Q);
printf("初始化已完成!\n\n");
int k = 1;
int Num = 1;
while (k==1) {
int Chose;
printf("\n");
printf("***请选择服务:***\n");
printf("***订餐请输入“0”,取餐请输入“1”***\n");
scanf_s("%d", &Chose);
printf("\n");
printf("------------------------------------------\n");
switch (Chose) {
case 0:
if (is_full(&Q)) {
printf("系统忙,请稍后……\n");
printf("------------------------------------------\n");
}
else{
en_queue(&Q, Num);
printf("--您已成功订餐,取餐号为 %d\n", Num);
printf("------------------------------------------\n");
}
break;
case 1:
if (is_empty(&Q)) {
printf("无法找到订餐信息!\n");
printf("------------------------------------------\n");
}
else {
int Num;
out_queue(&Q, &Num);
printf("--请%d号客户取餐,祝您用餐愉快!\n",Num);
printf("------------------------------------------\n");
}
break;
}
Num++;
}
}
if (Open == 0) {
QUEUE Q;
int val;
init(&Q);
if (is_empty(&Q)) {
printf("队列为空\n");
}
for (int i = 0; i <= MaxSize-1;i++) {
en_queue(&Q, i);
}
if (is_full(&Q)) {
printf("队列已满\n");
}
traverse(&Q);
out_queue(&Q, &val);
printf("出队列的值 = %d\n", val);
traverse(&Q);
out_queue(&Q, &val);
printf("出队列的值 = %d\n", val);
traverse(&Q);
printf("调试已完成,系统无故障!\n");
}
if (Open!=1 && Open!=0)
printf("请输入正确的开机指令!\n");
return 0;
}
运行成果展示: