利用静态队列实现订餐取餐系统

利用静态队列实现订餐取餐系统

如题。题主在一次吃肯德基的时候看到餐厅里的订餐取餐系统,突发奇想。联想到最近学习的队列的相关知识,准备动手用静态队列实现一个类似于现代餐厅的订餐取餐系统。由于题主没有学习过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;
}

运行成果展示:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值