✨写在前面
数据结构的课程设计一般都不是很好理解,于是我花时间总结了一下c和c++版本的常见栈和队列的的停车场管理程序。划重点,全注释!!!爆肝一天,绝对让你思路清晰的拿下该程序。
✨✨ 感兴趣的同学可以订阅一下我的这个《数据结构用心学》专栏喔~✨✨
✨目录
1、停车功能
如果停车场满,能够暂时存放到便道内
2、开走车功能
将指定车开走后打印收据,便道内的车自动停到停车场
3、退出程序功能
停车功能测试:
离开停车场并打印收据测试:
- #define _CRT_SECURE_NO_WARNINGS//visual stduio添加对scanf的信任
- #include<stdio.h>
- #include <stdlib.h>
- #include<string.h>
- #include<math.h>
- #define size 1 //停车场位置数
- //模拟停车场的堆栈的性质;
- typedef struct zanlind {
- int number; //汽车车号
- float ar_time; //汽车到达时间
- }zanInode;//车结点
- typedef struct {
- zanInode* base; //停车场的堆栈底
- zanInode* top; //停车场的堆栈顶
- int stacksize_curren;//堆栈长度
- }stackhead;
- //堆栈的基本操作;
- void initstack(stackhead& L) //构造一个空栈L
- {
- L.base = (zanInode*)malloc(size * sizeof(zanlind));//给栈L分配空间
- if (!L.base) exit(0); //存储分配失败
- L.top = L.base;//初始化栈顶和栈底指针相同
- L.stacksize_curren = 0;//初始化栈长度为0
- }
- void push(stackhead& L, zanInode e) //插入元素e为新的栈顶元素
- {
- *L.top++ = e;//先让L栈的栈顶指向e,然后栈顶指针+1
- L.stacksize_curren++;//由于上面的e进入了栈内,所以栈长度加一
- }
- void pop(stackhead& L, zanInode& e) //若栈不为空,删除L的栈顶元素,用e返回其值
- {
- if (L.base==L.top)//栈长度为0时,停车场为空
- {
- printf("停车场为空!!");
- return;
- }
- e = *--L.top;//如果栈顶和栈底不等,那么e为当前top指针减一后的指向,这是因为栈顶指针始终指向栈顶元素的上面。
- L.stacksize_curren--;//随着top指针减一,栈长度减一。注意返回e是通过引用完成的,就是 &e,e的变化会导致实参的变化
- }
- //模拟便道的队列的性质;
- typedef struct duilie {//队列就是便道(候车区)
- int number; //汽车车号
- float ar_time; //汽车到达时间
- struct duilie* next;//链式的队列结点,通过next指针访问相邻的队列结点
- }*queueptr;//指向队列结点自身的指针
- typedef struct {
- queueptr front; //便道的队列的对头
- queueptr rear; //便道的队列的队尾
- int length;//队列长度
- }linkqueue;
- //队列的基本操作;
- void initqueue(linkqueue& q) //构造一个空队列q,也是初始化
- {
- q.front = q.rear = (queueptr)malloc(sizeof(duilie));//给队列q动态分配空间
- if (!q.front || !q.rear)
- exit(0); //如果队首指针和队尾指针为NULL,则存储分配失败
- q.front->next = NULL;//队首指针的下一个队列结点置为NULL,队列结点进队列只能从队尾进
- q.length = 0;//初始化队列长度为零
- }
-
- void enqueue(linkqueue& q, int number, int ar_time) //进队列,把车结点插入队列尾(属性为number,ar_time)
- {
- queueptr p;//创建队列指针p
- p = (queueptr)malloc(sizeof(duilie));//为p分配空间
- if (!p) exit(0); //为空则存储分配失败
- p->number = number;//让队列结点的车牌号等于插入进来的车牌号
- p->ar_time = ar_time;//同上,给时间赋值
- p->next = NULL;//保证只能从队尾进队列
- q.rear->next = p;//将p结点插入到队尾
- q.rear = p;//此时队尾指针rear指向插入进来的p结点,方便下一次从队尾插入车结点信息
- q.length++;//插入后队列长度加一
- }
- void popqueue(linkqueue& q, queueptr& w) //删除q的队头元素 w(属性为number,ar_time)
- {
- queueptr p;//创建中间队列指针p
- if (q.length==0)//队首队尾指针相同则候车区无车
- {
- printf("停车场通道为空");
- return;
- }
- p = q.front->next;//p指针指向队列q中的队首位置
- w = p;//将队首元素赋值给w,即w代表删除的队首元素
- q.front->next = p->next;//删除队首元素
- q.length--;//删除后队列长度减一
- }
-
-
- float shijiancha(float x, float y) //求时间差的子程序,x是进入时间,y是离开时间
- {
- if (x > y) {
- printf("非法时间数据");
- return -1;
- }
- int shix, shiy, fenx, feny;
- float shijiancha;//返回值,待赋值
- shix = x;//shix为进入时间的整数部分
- shiy = y;//shiy为离开时间的整数部分
- fenx = (int)((x - shix) * 100);//fenx为进入时间的小数部分的100倍
- feny = (int)((y - shiy) * 100);//feny为离开时间的小数部分的100倍
- if (fenx > feny)
- {//如果fenx>feny,时间差就等于离开的整数减去进入的整数-1再加上60+feny-fenx,实际上feny-fenx是负数
- shijiancha = (shiy - shix - 1) + (float)(feny + 60 - fenx) / 100;
- }
- else//这个就是正常的了,整数部分减加上小数部分减即可
- shijiancha = (shiy - shix) + (float)(feny - fenx) / 100;
- return shijiancha;//返回值为时间差
- }
-
-
- void jinru(stackhead& st, linkqueue& q) //对进入停车场的汽车的处理;
- {
- int number;//待使用的车牌号
- float time_a;//待使用的时间
- printf("请输入车牌号:");
- scanf("%d", &number);//
- printf("请输入您进车场的时间(比如说:8点半则输入8.30):"); scanf("%f", &time_a);
- if (st.stacksize_curren < 2)//停车场可以停2辆车,大于两辆车执行else的语句
- {
- zanInode e;//创建车结点
- e.number = number;//给车牌号赋值
- e.ar_time = time_a;//给车时间赋值
- push(st, e);//将赋值好的车结点入栈
- printf("请把你的车停在%d号车道\n\n", st.stacksize_curren);//提示车停在了哪个车道
- }
- else//如果执行这段代码,说明停车场以及停满2辆车
- {
- enqueue(q, number, time_a);//将车停入候车区,也就是便道
- printf("停车场已满,请把你的车停在便道的第%d个位置上\n", q.length);
- }
- }
-
-
- void likai(stackhead &st, stackhead &sl, linkqueue &q) //对离开的汽车的处理;
- { //st 堆栈为停车场,sl 堆栈为倒车场
- int number, flag = 1; //q 为便道队列
- float sh, time_d, arrivaltime, money1;
- printf("请输入您的车牌号:"); scanf("%d", &number);
- printf("请输入您出车场的时间(比如说:8点半则输入8.30):"); scanf("%f", &time_d);
- zanInode e, q_to_s;//e为要查找的车结点,q_to_s为后面将从便道进入停车场的车结点
- queueptr w;//队列指针,待使用
- while (flag) //此时flag=1,死循环
- {
- pop(st, e);//取出栈顶结点
- push(sl, e);//将取出的栈顶结点放入倒车场
- if (e.number == number)//如果车牌号对应
- {
- flag = 0;//flag变为0,死循环结束
- arrivaltime = e.ar_time;//将该结点的进入时间赋值给arrivaltime
- sh = shijiancha(arrivaltime, time_d);//带入计算时间差的函数并将时间差赋值给sh
- money1 = (int)sh * 2 + (sh - (int)sh) * 100 / 30;//收费依据
- }
- }
- pop(sl, e); //把倒车场的第一辆车(要离开的)去掉;
- while (sl.stacksize_curren) //把倒车场的车倒回停车场
- {
- pop(sl, e); //取出栈顶结点
- push(st, e);//将取出的栈顶结点放入倒车场
- }
- if (st.stacksize_curren < 2 && q.length != 0) //停车场有空位,便道上的车开进入停车场
- {
- popqueue(q, w);//取出便道的第一个车并把其信息赋值给w指针
- q_to_s.ar_time = w->ar_time;//将该车信息赋值给q_to_s结点
- q_to_s.number = w->number;
- push(st, q_to_s);//入栈,即停车
- printf("车牌为%d 的车已从通道进入停车场, 所在的停车位为 %d:\n", q_to_s.number, st.stacksize_curren);
- }
- printf("\n 收据");
- printf("车牌号:%d\n", number);
- printf("++++++++++++++++++++++++++++++\n");
- printf(" 进车场时间:%4.2f\n", arrivaltime);
- printf(" 出车场时间:%4.2f\n", time_d);
- printf(" 停留时间:%4.2f\n", sh);
- printf(" 应付(元) %4.2f\n", money1);
- printf("++++++++++++++++++++++++++++++\n\n");
- }
-
-
- int main()
- {
- int m = 100;
- int choose; //进入或离开的标识;
- stackhead sting, slinshi; //停车场和临时倒车场堆栈的定义;
- linkqueue line; //队列的定义;
- initstack(sting); //构造停车场堆栈sting
- initstack(slinshi); //构造倒车场堆栈slinshi
- initqueue(line); //构造便道队列line
- printf("\n ******************停车场管理程序*************** ");
- printf("\n*===========================================================*");
- printf("\n*温馨提示:请车主在24:00之前来取车,给您带来的不便,敬请原谅!*");
- printf("\n* 1 *** 汽车进车场 2 *** 汽车出车场 3 *** 退出程序 *");
- printf("\n*===========================================================*\n");
- while (m)//m为100,可以重复操作100次
- {
- printf(" 请输入您需要的服务的代号(1、2、3),谢谢!\n");
- scanf("%d", &choose);//待选择的操作
- switch (choose)
- {
- case 1: jinru(sting, line); break; //汽车进车场
- case 2: likai(sting, slinshi, line); break; //汽车出车场
- case 3: exit(0);//退出
- }
- --m;//m递减
- }
- }
1、停车功能
如果停车场满,能够暂时存放到便道内
2、开走车功能
将指定车开走后自动计费,便道内的车自动停到停车场
3、查看停车场停车情况功能
可以查看停车场有无空位和停车信息。
4、退出程序功能
停车功能测试:
离开停车场并自动计费测试:
查看停车场状况功能测试:
- #define _CRT_SECURE_NO_WARNINGS//visual stduio添加对scanf的信任
- #include <stdio.h>
- #include <stdlib.h>
- #include <iostream>//C++IO流头文件
- using namespace std;//C++命名空间,配合IO流头文件可使用cin>>输入,cout<<输出
- #define MaxSize 5 //停车场最大停车位
- #define fee 2 //一小时的费用
- #define L 10000//宏定义
- typedef int ElemType;//将整型int名字变为ElemType,下面再使用ElemType就是整型的意思
- ElemType tmpnum = 0;//车牌号
- ElemType tmptime = 0;//进入时间
- typedef struct {
- ElemType car_num[MaxSize];//车牌号数组
- ElemType car_time[MaxSize];//进入时间数组
- int top;//数组下标
- }STACK;//栈,存放所有的车牌号和进入时间数组
- typedef struct qnode {//队列结点
- ElemType car_num;//包含车牌号
- ElemType car_time;//和进入时间
- struct qnode* next;//指向自身的指针,用来当问相邻队列结点
- }QTYPT;//将qnode重命名为QTYPT
- typedef struct qptr {//队列
- QTYPT* front;//队首指针
- QTYPT* rear;//队尾指针
- }SQUEUE;//将qptr重命名为SQUEUE
- void InitStack(STACK* S) {//初始化栈S
- S->top = -1;//数组下标初始化为-1
- }
-
- int Full(STACK* S) {//栈满的情况
- if (S->top == MaxSize - 1) {
- printf("\n Stack is full! Push");//提示栈满
- return 0;
- }
- return 1;
- }
- //入栈函数Push
- int Push(STACK* S, ElemType num, ElemType time) {
- if (S->top == MaxSize - 1) {
- printf("\n Stack is full! Push");//栈满提示,并退出
- return 0;
- }
- S->top++; //栈不满时数组下标加一,此时为0
- S->car_num[S->top] = num; //栈车牌号数组的car_num[top]赋值为num
- S->car_time[S->top] = time; //同车牌号,这次是进入时间的赋值
- return 1; //赋值成功则返回1
- }
-
- int Empty(STACK* S) {//栈空的情况
- return (S->top == -1 ? 1 : 0);//栈空返回1
- }
- //出栈函数Pop
- int Pop(STACK* S, ElemType* num, ElemType* time) {
- if (Empty(S)) {//栈空无法出栈
- puts("Stack is free Pop");
- return 0;
- }//栈不空时
- *num = S->car_num[S->top]; //将栈顶的车牌号赋值给*num
- *time = S->car_time[S->top];//赋值时间给*time
- S->top--;//出栈后数组下标减一
- return 1;
- }
- //初始化队列
- void InitQueue(SQUEUE* LQ) {
- QTYPT* p = NULL;//创建队列结点指针
- p = (QTYPT*)malloc(sizeof(QTYPT));//为p职责和你分配空间
- p->next = NULL;//使p指针的next为空,相当于头结点
- LQ->front = LQ->rear = p;//初始化队首和队尾指针指向头结点p,
- }
- //将队列结点入队
- int EnQueue(SQUEUE* LQ, ElemType num, ElemType time) {
- QTYPT* s;//创建s指针
- s = (QTYPT*)malloc(sizeof(QTYPT));//分配空间
- s->car_num = num;//将车牌号赋值给p指向的车牌号
- s->car_time = time;//赋值时间
- s->next = LQ->rear->next;//将s结点插入到队尾的下一个位置
- LQ->rear->next = s;//队尾指针的下一个位置指向s
- LQ->rear = s;//队尾指针指向新插入的结点,这样时头插法,符合队列后进后出的特点
- return 1;
- }
- //计算队列有多少结点
- int CountQueue(SQUEUE* LQ) {
- int i = 1;
- QTYPT* mfront = NULL;//创建该队列的新队首指针
- QTYPT* mrear = NULL;//创建新队尾指针
- mfront = LQ->front;//将队首指针赋值给新队首指针,记录作用
- mrear = LQ->rear;//同上
- while (!(LQ->front == LQ->rear)) {//当队首不等于队尾指针时,i++,统计的结点个数增加
- i++;
- LQ->front = LQ->front->next;//队首指向队首的下一个位置
- }
- LQ->front = mfront;//统计完成后将队首指针指向原来的地址
- return i;//i为结点个数
- }
-
- int Empty_Q(SQUEUE* LQ) {//队列为空
- return (LQ->front == LQ->rear ? 1 : 0);
- }
-
- int OutQueue(SQUEUE* LQ, ElemType* num, ElemType* time) {//取队首
- QTYPT* p;//创建对列结点指针
- if (Empty_Q(LQ)) {//队列空不能取队首
- puts("Quenue is free OutQuenue");
- return 0;
- }
- p = LQ->front->next;//p指向队首结点
- *num = p->car_num;//将队首结点信息赋值
- *time = p->car_time;
- LQ->front->next = p->next;//删除队首结点
- if (LQ->front->next == NULL)//如果队首结点不存在
- LQ->rear = LQ->front;//队首队尾指针相同,队空
- free(p);//释放p结点
- return 1;
- }
- //检查有无重复车牌号
- int chackinput(STACK* S, int pnum) {
- int i = 0;
- int num;
- num = pnum;//将车牌号赋值
- i = S->top;//i为栈顶位置的数组下标
- for (; !(i == -1); i--)//从高到底遍历car_num数组,找到车牌号返回1,否则返回0
- if (S->car_num[i] == num)
- return 1;
- return 0;
- }
- //检查时间输入是否合理
- int chacktime(STACK* S, int ptime) {
- return S->car_time[S->top] <= ptime ? 1 : 0;//只有离开时间大于进入时间才能赋值成功
- }
- //显示停车场内状况
- int displaystats(STACK* S, int pinput) {
- void displayhead();//显示菜单
- int i = 0;
- i = S->top;//i为栈顶位置的数组下标
- switch (pinput)//调用的时候自动填入10000
- {
- case 10000:
- {
- if (!Empty(S))//栈不空
- for (; !(i == -1); i--)//遍历输出栈内停车信息
- printf("<===%d时%d号车停于%d车位===>\n", S->car_time[i], S->car_time[i], i + 1);
- else
- cout << "停车场为空";
- printf("还有车%d个位\n", MaxSize - S->top - 1);//剩余车位等于最大停车位-当前数组下标再-1,因为数组是从0开始
- break;
- }
- default:
- {
- return 1;
- }
- }
- return 0;
- }
- //功能菜单
- void displayhead() {
- cout << '\n' << "<===============CT停车场管理系统===================>" << endl;
- cout << "<==操作说明: ******* ==>" << endl;
- cout << "<==1: 停车命令 ******* ==>" << endl;
- cout << "<==2: 出车命令 *** ==>" << endl;
- cout << "<==0: 退出程序 *** ==>" << endl;
- cout << "<==3: 显示停车场内状况 " << endl;
- cout << "<==============================================>" << endl;
- }
- //打印收费条
- void displayChange(STACK* S, ElemType pnum, int ptime) {
- printf(" (单价 %d元/小时 )\n", fee);//fee在宏定义有,值为2
- printf("<======================电子收据===================>\n");
- printf("<==停车时间:--------------------------%d小时 ==>\n", ptime - tmptime);//停车时长
- printf("<==车牌号码:--------------------------%d ==>\n", tmpnum);//打印车牌号
- printf("<==应收费用:--------------------------%d 元 ==>\n", (ptime - tmptime) * fee);//计算费用
- printf("<====================谢谢=欢迎下次再来=============>\n");
-
- }
- //开走车
- int outparkstation(STACK* S1, STACK* TS, ElemType pnum) {
- int t_num = 0;
- int t_time = 0;
- while (1) {
- Pop(S1, &t_num, &t_time);//取出栈顶车
- if (t_num == pnum) {//如果这一次取出的栈顶车的车牌号是我们想开走的
- tmpnum = t_num;//进行车牌号和进入时间的赋值
- tmptime = t_time;
- while (!Empty(TS)) {//当备用停车场不空时
- Pop(TS, &t_num, &t_time);//循环取出备用停车场的暂存栈顶车
- Push(S1, t_num, t_time);//将每次的栈顶车再放进停车场
- }
- return 1;//结束循环
- }
- Push(TS, t_num, t_time);//栈顶不是我们想要的车就暂存再备用停车场
- }
- return 0;
- }
- //进行停车
- int inparkstation(STACK* S) {
- int parknum;
- int parktime;
- printf("还有%d个车位\n", MaxSize - S->top - 1);
- printf("请输入车牌号码:");
- cin >> parknum;//输入车牌号
- while (chackinput(S, parknum)) {//调用检验函数,重复则重新输入车牌号
- printf("车牌号码重复,请输入%d1或者其他", parknum);
- cin >> parknum;//输入车牌号
- }
- printf("请输入停车时间:");
- cin >> parktime;//输入停车时间
- printf("%d号车于%d时停靠在%d位\n", parknum, parktime, S->top + 2);//下标加2是因为初始为-1,第一个车位于一号位,需要加2
- Push(S, parknum, parktime);//将输入的车牌号与进入时间入栈,完成停车
- return 1;
- }
- //在便道,栈满时将车暂存到便道内
- int inbiandao(SQUEUE* SQ, STACK* S) {
- int parknum;
- printf("对不起,停车场已满,请您到便道等待.停车场有空位时您将第");
- printf("%d进入停车场\n", CountQueue(SQ));//调用CountQueue()函数,得到便道内的结点个数
- printf("请输入车牌号码:");
- cin >> parknum;
- while (chackinput(S, parknum)) {//如果有重复车牌号则重新输入
- printf("车牌号码重复,请输入其他车牌号");
- cin >> parknum;
- }
- EnQueue(SQ, parknum, 0);//将车牌号为parknum的车放进便道,进便道时间默认为0
- return 1;
- }
- //离开停车场
- int OutParkingStation(SQUEUE* biandao, STACK* car, STACK* tmp) {
- int parknum = 0;
- int parktime = 0;
- int buf = 0;
- if (!Empty(car)) {//栈不空的情况下
- displaystats(car, 10000);//遍历查看停车场停车情况
- printf("请输入您要调出的车牌号码:");
- cin >> parknum;
- while (!chackinput(car, parknum)) {
- printf("没有您要的%d的车牌号码,请输入正确的车牌号码:", parknum);//没有检查到重新输入
- cin >> parknum;
- }
- outparkstation(car, tmp, parknum);//将车牌号为parknum的车开走
- printf("%d时%d号车进入停车场\n", tmptime, tmpnum);//上一行代码已经给开走的车进入时间和车牌号赋值,
- printf("请输入现在的时间:");//开走时的时间
- cin >> parktime;
- while (!chacktime(car, parktime)) {//开走时间需要大于进入时间,否则重新输入
- cout << "输入时间小于停车时间,请重新输入:";
- cin >> parktime;
- }
- displayChange(car, parknum, parktime);//打印账单
- if (biandao->front != biandao->rear)
- {
- printf("%d号车位空开\n", car->top + 2);//提示开走的车占用的停车场位置空了
- printf("%d时便道上的%d号汽车驶入%d号车位", parktime, biandao->front->next->car_num, car->top + 2);//提示便道队首元素进入停车场
- OutQueue(biandao, &parknum, &buf);//将便道队首元素的车牌号赋值给parknum
- Push(car, parknum, parktime);//将该车进入停车场栈顶,进入成功
- }
- return 2;
- }
- printf("停车场为空\n");//栈空则停车场为空
- return 1;
- };
-
- int main() {
- int chance = 0;//用来选择操作
- STACK car;//创建未分配空间的car栈
- InitStack(&car);//初始化,包括分配内存空间
- STACK tmp;//备用栈
- InitStack(&tmp);//初始化
- SQUEUE biandao;//创建队列
- InitQueue(&biandao);//初始化
- loop://跳转语句,配和goto语句使用
- while (1) {
- displayhead();//展示菜单
- cout << "=>:";
- cin >> chance;//输入操作的选择
- switch (chance) {
- case 1:
- {
- printf("查询结果为:\n");
- if (Full(&car))//栈未满时执行if,栈满时执行else
- inparkstation(&car);//停进停车场
- else
- inbiandao(&biandao, &car);//停进便道
- break;
- }
- case 2:
- {
- OutParkingStation(&biandao, &car, &tmp);//开走车
- break;
- }
- case 3:
- {
- displaystats(&car, 10000);//查看停车场信息
- break;
- }
- case 0:
- {
- printf("成功退出,欢迎下次使用!");
- return 0;//退出循环
- }
- default:
- {
- cout << "输入错误" << endl;
- goto loop;//goto语句是跳转的意思,跳转到前面的loop位置,即继续选择操作
- }
- }
- }
- system("PAUSE");//终端出现按任意键继续,终端就是显示运行结果的地方
- return 0;
- }
爆肝万字的两个版本的停车场管理程序你爱了吗,反正我是累死了。在最后希望家人们给个三连支持哇,你们的鼓励是我创作的不竭动力!!!