【数据结构】停车场管理系统程序设计

说明:该程序设计采用常见基础的数据结构栈和队列实现了一个简单停车场管理系统。在具体设计中,实现了系统页面和停车场的示意图显示,通过调用顺序栈和链队的相关函数,模拟了实际停车场的运营流程。


目录

1 任务内容

2 需求分析

2.1 功能需求

2.2 输入输出需求

3 概要设计

3.1 抽象数据类型

3.2 具体功能函数

4 详细代码

5 使用说明

6 测试结果与分析

7 总结感悟


1 任务内容

任务描述:设停车场(如下图所示)内只有一个可停放几量汽车的狭长通道,且只有一个大门可供汽车进出。汽车在停车场内按车辆到达时的先后顺序,依次由北向南排列(大门在最南端,最先到达的第一辆车停放在车场的最北端),若车场内已经停满几量汽车,则后来的汽车只能在门外的便道上等候,一旦停车场内有车开走,则排在便道上的第一辆汽车即可开入;当停车场内某车辆要离开时,由于停车场是狭长的通道,在它之后开入车场的车辆必须先退出车场为它让路,待该车辆开出大门外后,为它让路的车辆再按原次序进入车场。在这里假设汽车不能从便道上开走。试设计一个停车场管理程序(这里只是一个假想的停车场管理,并不代表实际的停车场管理)。

分析提示:汽车在停车场内进出是按照栈的运算方式来实现的,先到的先进停车场;停车场的汽车离开停车场时,汽车场内其它汽车为该辆汽车让路,也是按栈的方式进行;汽车在便道上等候是按队列的方式进行的。因此,将停车场设计成一个栈,汽车让路也需要另一个栈来协助完成,汽车进出便道用队列来实现。

基本要求

1)接受命令和车号,若是汽车要进停车场,先判断停车场栈是否满,若不满,则汽车入栈,否则汽车进入便道队列等候。

2)若是汽车要离开停车场,为给汽车让路,将停车场栈上若干辆汽车入临时栈,等这辆车出停车场后,临时栈中的汽车出栈,在回到停车场栈,然后看便道队列是否为空,若不空则说明有汽车等候,从队头取出汽车号,让该车进入停车场栈。

3)重复1),2)直到为退出命令(车号为0或负数)。

数据结构:本设计中,栈采用顺序栈结构,队列用链式存储结构。

核心知识:栈和队列。

2 需求分析

2.1 功能需求

一、界面设计

1. 停车场管理系统界面

2. 停车场字符模拟示意图

2. 便道字符模拟示意图

二、停车场管理

1. 车辆停放:包括车辆停放操作、便道等候操作

2. 车辆离开:包括车辆离开操作、便道车辆停放操作

3. 停车场状态:显示当前停车场和便道的车辆状态

4. 打印停车场车辆信息:显示当前停车场示意图

5. 打印便道车辆信息:显示当前便道示意图

2.2 输入输出需求

一、系统界面

输出:“欢迎使用STRANGEX-03停车场管理系统”字样、停车场管理功能模块等内容。

输入:单个字符“A”“B”“C”等内容表示要选择的功能模块或退出系统的操作。

输出:执行对应功能模块的相关操作。

二、车辆停放模块(在系统界面输入A

输出:当前停车场和便道的车辆状态,提示字样如“当前空余车位为X,便道上共有X辆车在等待,您确定要停车吗”。

(一)同意停放车辆

输入:单个字符“Y”表示同意。

输出:“请输入您的车辆编号”字样

输入:5位整型数字表示车辆编号

输出:“您的车辆已停放到停车场”或“您的车辆正在便道等待”

(二)拒绝停放车辆

输入:单个字符“N”表示拒绝。

输出:返回系统界面

三、车辆离开模块(在系统界面输入B

输出:提示字样如“请输入您的车辆编号”

输入:5位整型数字表示车辆编号

(一)便道上没有车辆

输出:执行操作后提示“该车辆已离开,X车辆已停入停车场,便道现有X辆车在等待”,

(二)便道上有车辆

输出:“该车辆已离开停车场”

四、停车场状态模块(在系统界面输入C

输出:当前停车场和便道的车辆状态,字样如“停车场共有%d个车位,当前空余车位为%d,便道上共有%d辆车在等待”

五、停车场车辆信息模块(在系统界面输入D

输出:当前停车场的模拟示意图

六、便道车辆信息模块(在系统界面输入E

输出:当前便道的模拟示意图

3 概要设计

3.1 抽象数据类型

本程序共设计三个抽象数据类型分别表示停车场栈、通道车辆结点和便道队列。

//停车场栈

typedef struct{
    int data[StackSize];
    int top;
} SqStack;

//通道车辆结点

typedef struct linked_queue{
    int data;
    struct linked_queue *next;
} DataNode;

//便道队列

typedef struct{
    DataNode *front;
    DataNode *rear ;
} LinkQuNode;

3.2 具体功能函数

本程序共有22个功能函数,具体包括4个界面设计函数、5个停车场管理函数、7个栈操作函数、6个队列操作函数。

//界面设计函数

void MainMenu();                            //主菜单界面
void TouchMenu(SqStack *&s,LinkQuNode *&q); //菜单触控操作
void ParkingLot(SqStack *s);                //停车场模拟界面
void WaitingRoad(LinkQuNode *&q);           //便道模拟界面

//停车场管理函数

void ToPark(SqStack *&s,LinkQuNode *&q);    //车辆停放操作
void ToLeave(SqStack *&s,LinkQuNode *&q);   //车辆离开操作
void GetStatus(SqStack *s,LinkQuNode *q);   //显示当前停车场和便道状态
void GetParking(SqStack *s);                //打印当前停车场车辆信息
void GetWaiting(LinkQuNode *&q);            //打印当前便道车辆信息

//栈操作函数

void InitStack(SqStack *&s);          //初始化栈
void DestroyStack(SqStack *&s);       //销毁栈
bool StackEmpty(SqStack *s);          //判断栈是否为空
bool Push(SqStack *&s,int e);         //入栈操作
bool Pop(SqStack *&s,int &e);         //出栈操作
bool GetTop(SqStack *s,int &e);       //获取栈顶元素
int CountStack(SqStack *s);           //计算栈内元素个数

//队列操作函数

void InitQueue(LinkQuNode *&q);        //初始化队列
void DestroyQueue(LinkQuNode *&q);     //销毁队列
bool QueueEmpty(LinkQuNode *q);        //判断队列是否为空
bool enQueue(LinkQuNode *&q,int e);    //入队操作
bool deQueue(LinkQuNode *&q,int &e);   //出队操作
int CountQueue(LinkQuNode *q);         //计算队列内元素个数

4 详细代码

#include<bits/stdc++.h>
using namespace std;
const int StackSize=10;

//抽象数据类型
//停车场栈
typedef struct{
    int data[StackSize];
    int top;
} SqStack;

//便道车辆结点
typedef struct linked_queue{
    int data;
    struct linked_queue *next;
} DataNode;

//通道队列
typedef struct{
    DataNode *front;
	DataNode *rear ;
} LinkQuNode;



//具体功能函数列表
//界面设计函数
void MainMenu();
void TouchMenu(SqStack *&s,LinkQuNode *&q);
void ParkingLot(SqStack *s);
void WaitingRoad(LinkQuNode *&q);

//停车场管理函数
void ToPark(SqStack *&s,LinkQuNode *&q);
void ToLeave(SqStack *&s,LinkQuNode *&q);
void GetStatus(SqStack *s,LinkQuNode *q);
void GetParking(SqStack *s);
void GetWaiting(LinkQuNode *&q);

//栈操作函数
void InitStack(SqStack *&s);
void DestroyStack(SqStack *&s);
bool StackEmpty(SqStack *s);
bool Push(SqStack *&s,int e);
bool Pop(SqStack *&s,int &e);
bool GetTop(SqStack *s,int &e);
int CountStack(SqStack *s);

//队列操作函数
void InitQueue(LinkQuNode *&q);
void DestroyQueue(LinkQuNode *&q);
bool QueueEmpty(LinkQuNode *q);
bool enQueue(LinkQuNode *&q,int e);
bool deQueue(LinkQuNode *&q,int &e);
int CountQueue(LinkQuNode *q);



int main(){
	SqStack *park;//定义停车场栈
	LinkQuNode *wait;//定义通道队列
	InitStack(park);
	InitQueue(wait);
	//调试专用数据
	Push(park,12345);
	Push(park,67890);
	Push(park,63465);
	Push(park,89986);
	Push(park,53845);
	Push(park,65374);
	Push(park,15555);
	Push(park,25389);
	Push(park,24389);
	TouchMenu(park,wait);
	return 0;
}

//主菜单页面
void MainMenu(){
	printf("      * * * * * * * * * * * * * * * * * * *\n");
	printf("      * 欢迎使用STRANGEX-03停车场管理系统 *\n");
	printf("      * * * * * * * * * * * * * * * * * * *\n");
	printf("      *      [A]车辆停放模块              *\n");
	printf("      *      [B]车辆离开模块              *\n");
	printf("      *      [C]显示当前停车场运营状态    *\n");
	printf("      *      [D]打印停车场内的车辆信息    *\n");
	printf("      *      [E]打印便道上的车辆信息      *\n");
	printf("      *      [Z]退出系统                  *\n");
	printf("      * * * * * * * * * * * * * * * * * * *\n");
	printf("请输入字母选择你要使用的功能模块:");
}

//菜单触控
void TouchMenu(SqStack *&s,LinkQuNode *&q){
	char c;
	MainMenu();
	while(scanf("%c",&c)){
		switch(c){
			case 'A':
				ToPark(s,q);
				MainMenu();
				break;
			case 'B':
				ToLeave(s,q);
				MainMenu();
				break;
			case 'C':
				GetStatus(s,q);
				MainMenu();
				break;
			case 'D':
				GetParking(s);
				MainMenu();
				break;
			case 'E':
				GetWaiting(q);
				MainMenu();
				break;
			case 'Z':
				printf("\n欢迎再次使用STRANGEX-03停车场管理系统,再见!");
				return;
			default:
				printf("请输入正确的字母:");
		}
		c=getchar();//消除回车对程序的影响
	}
}

//停车场模拟界面
void ParkingLot(SqStack *s){
	printf("    @ @ @ @ @ @ @       ↑\n");
	for(int i=0;i<StackSize;i++){
		printf("    @ ");
		if(i<CountStack(s)){
			printf("车辆%d",s->data[i]);
			printf(" @");
		}
		else{
			printf("          @");
			
		}
		if(i==0){
			printf("       北");
		}
		else if(i==StackSize-2){
			printf("       ↓");
		}
		else if(i==StackSize-1){
			printf("       南");
		}
		else if(i==StackSize/2-1){
			printf("  停车场示意图");
		}
		printf("\n");
	}
}

//便道模拟界面 
void WaitingRoad(LinkQuNode *&q){
	
	printf("        ");
	for(int i=0;i<CountQueue(q);i++){
		printf("@ @ @ @ @ @ ");
	}
	printf("@ @\n");
	printf(" 出口 ← ");
	DataNode *car=q->front;
	int k=0;
	if(car!=NULL){
		while(car->next!=NULL){
			printf(" | 车辆%d",car->data);
			car=car->next;
		}
		printf(" | 车辆%d | ",car->data);
	}
	else {
		printf("   ");
	}
	printf(" ← 入口     便道示意图\n");
	printf("        ");
	for(int i=0;i<CountQueue(q);i++){
		printf("@ @ @ @ @ @ ");
	}
	printf("@ @\n");
}



//车辆停放
void ToPark(SqStack *&s,LinkQuNode *&q){
	printf("\n※当前功能模块:[A]车辆停放模块\n");
	printf("---------------------------------------------------------------------\n");
	printf("当前空余车位为%d,便道上共有%d辆车在等待,您确定要停车吗?\n",StackSize-CountStack(s),CountQueue(q));
	int c;
	printf("请输入[Y/N]:");
	scanf("%c",&c);
	c=getchar();
	if(c=='Y'){
		int carNo;
		printf("请输入车辆编号:");
		scanf("%d",&carNo);
		if(Push(s,carNo)){
			printf("车辆%d已成功停放在停车场\n",carNo);
		}
		else{
			enQueue(q,carNo);
			printf("停车场已满,车辆%d正在便道上等候\n",carNo);
		}
	}
	else if(c=='N'){
		printf("您已确认不停车,自动返回主菜单\n");
	}
	else if(c!='N') {
		printf("输入错误,自动返回主菜单\n");
	}
	printf("---------------------------------------------------------------------\n");
	printf("\n");
	return;
}

//车辆离开
void ToLeave(SqStack *&s,LinkQuNode *&q){
	printf("\n※当前功能模块:[B]车辆离开模块\n");
	printf("---------------------------------------------------------------------\n");
	int carNo;
	int No=-1;
	printf("请输入您的车辆编号:");
	scanf("%d",&carNo);
	for(int i=0;i<CountStack(s);i++){
		if(carNo==s->data[i]){
			No=i;
			break;
		}
	}
	if(No==-1){
		printf("对不起,没有找到您的车辆,自动返回主菜单\n");
	}
	else {
		SqStack *temp;
		int e;
		InitStack(temp);
		int x=CountStack(s);
		for(int i=x-1;i>No;i--){
			Pop(s,e);
			Push(temp,e);
		}
		Pop(s,e);
		for(int i=x-1;i>No;i--){
			Pop(temp,e);
			Push(s,e);
		}
		if(!QueueEmpty(q)){
			deQueue(q,e);
			Push(s,e);
			printf("车辆%d已离开,车辆%d已成功停放在停车场,便道还有%d辆车在等待\n",carNo,e,CountQueue(q)); 
		}
		else {
			printf("车辆%d已离开停车场\n",carNo);
		}
	}
	printf("---------------------------------------------------------------------\n");
	printf("\n");
	return;
}

//停车场状态
void GetStatus(SqStack *s,LinkQuNode *q){
	printf("\n※当前功能模块:[C]显示当前停车场运营状态\n");
	printf("---------------------------------------------------------------------\n");
	printf("停车场共有%d个车位,当前空余车位为%d,便道上共有%d辆车在等待\n",StackSize,StackSize-CountStack(s),CountQueue(q));
	printf("---------------------------------------------------------------------\n");
	printf("\n");
	return;
}

//打印停车场车辆信息
void GetParking(SqStack *s){
	printf("\n※当前功能模块:[D]打印停车场内的车辆信息\n");
	printf("---------------------------------------------------------------------\n");
	ParkingLot(s);
	printf("---------------------------------------------------------------------\n");
	printf("\n");
}

//打印便道车辆信息
void GetWaiting(LinkQuNode *&q){
	printf("\n※当前功能模块:[E]打印便道上的车辆信息\n");
	printf("---------------------------------------------------------------------\n");
	WaitingRoad(q); 
	printf("---------------------------------------------------------------------\n");
	printf("\n");
}



//栈操作函数
//初始化栈
void InitStack(SqStack *&s){
	s=(SqStack *)malloc(sizeof(SqStack));
	s->top=-1;
}

//销毁栈
void DestroyStack(SqStack *&s){
	free(s);
}

//判断栈是否为空
bool StackEmpty(SqStack *s){
	return (s->top==-1);
}

//进栈
bool Push(SqStack *&s,int e){
	if(s->top==StackSize-1)
		return false;
	s->top++;
	s->data[s->top]=e;
	return true;
}

//出栈
bool Pop(SqStack *&s,int &e){
	if(s->top==-1)
		return false;
	e=s->data[s->top];
	s->top--;
	return true;
}

//取栈顶元素
bool GetTop(SqStack *s,int &e){
	if(s->top==-1)
		return false;
	e=s->data[s->top];
	return true;
}

//返回栈的元素个数
int CountStack(SqStack *s){
	return s->top+1;
}



//队列操作函数
//初始化
void InitQueue(LinkQuNode *&q){
    q=(LinkQuNode *)malloc(sizeof(LinkQuNode));
    q->front=q->rear=NULL;
}

//销毁队列
void DestroyQueue(LinkQuNode *&q){
    DataNode *pre=q->front,*p;
    if(pre!=NULL){
        p=pre->next;
        while(p!=NULL){
            free(pre);
            pre=p;
            p=p->next;
        }
        free(pre);
    }
    free(q);
}

//判断队列是否为空
bool QueueEmpty(LinkQuNode *q){
	return q->rear==NULL;
}

//进队列
bool enQueue(LinkQuNode *&q,int e){
    DataNode *p;
    p=(DataNode *)malloc(sizeof(DataNode));
    p->data=e;
    p->next=NULL;
    if(q->rear==NULL)
        q->front=q->rear=p;
    else{
        q->rear->next=p;
        q->rear=p;
    }
    return true;
}

//出队列
bool deQueue(LinkQuNode *&q,int &e){
    DataNode *t;
    if(q->rear==NULL)
        return false;
    t=q->front;
    if(q->front==q->rear)
        q->front=q->rear=NULL;
    else
        q->front=q->front->next;
    e=t->data;
    free(t);
    return true;
}

//返回队列的元素个数
int CountQueue(LinkQuNode *q){
	int sum=1;
	DataNode *a=q->front,*b=q->rear;
	if(a==NULL&&a==b)
		return 0;
	while(a!=b){
		sum++;
		a=a->next;
	}
	return sum;
}

5 使用说明

系统界面共有五个功能选项和一个退出系统选项,选择不同选项根据提示进入下一步操作:

选择[A]:进入车辆停放模块。

选择[B]:进入车辆离开模块。

选择[C]:进入显示当前停车场运营状态模块。

选择[D]:进入打印停车场内的车辆信息模块。

选择[E]:进入打印便道上的车辆信息模块。

选择[Z]:显示“欢迎再次使用STRANGEX-03停车场管理系统,再见!”并退出系统,结束程序。

6 测试结果与分析

为便于调试显示,前期对停车场栈进行以下操作,存入部分数据。

Push(park,12345);
Push(park,25345);
Push(park,67890);
Push(park,89986);
Push(park,53845);
Push(park,65374);
Push(park,15555);
Push(park,25389);
Push(park,24389);
输入数据调试截图

A

Y

54321

A

Y

89745

A

Y

88888

C
D
E

B

54321

E
Z

 

7 总结感悟

在完成栈和队列知识梳理后进行本次程序设计,进一步巩固了对栈和队列的理解。题目本身难度不大,主要就根据任务的意思模拟了相关操作就能实现。

此次设计中主要遇到的一个比较大的问题是,无法实现向栈和队列中添加string类型数据,运行到相关Push操作和enQueue操作时提示“Thread 1 received signal SIGSEGV, segmentation fault.”,也就导致了标识车辆时只能使用整型数字表示车辆编号,而无法使用string字符串(即模拟车牌号)进行标识。这个问题目前仍未解决,网上也找不到相关的资料,可待后续再研究一下。

本次为了提升对于栈和队列应用的理解,没有使用C++内置的STL栈和队列。但其实对于相关的函数可以使用类进行封装,此前在Java中学习了面向对象的相关知识,但在C++中还未实现过,这也是后续可以学习实践的方向。

  • 19
    点赞
  • 61
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
实验二 停车场管理 班级:A0712 学号:12 姓名:冷清淼 成绩:__________ 指导教师签名:__________ 一、问题描述 设停车场是一个可停放n辆车的狭长通道,且只有一个大门可供汽车进出。在停车场 ,汽车按到达的先后次序,由北向南依次排列(假设大门在最南端)。若停车场已停满 n辆车,则后来的汽车需在门外的便道上等候,当有车开走时,便道上的第一辆车即可开 入。当停车场某辆车要离开时,在它之后进入的车辆必须先退出停车场为它让路,待该 辆车开出大门后,其他车辆再按原次序返回车场。每辆车离开停车场时,应按其停留时 间的长短交费(在便道上停留的时间不收费)。 设计要求: 1.模拟上述管理过程。要求以顺序栈模拟停车场,以链队列模拟便道。 2.从终端读入汽车到达或离去的数据,每组数据包括三项: (1)是"到达"还是"离开"; (2)汽车牌照; (3)"到达"或"离开"的时刻。 3.与每组输入信息相应的输出信息为:如果是到达的车辆,则输出其在停车场中或 便道上的位置;如果是离去的车辆,则输出其在停车场中停留的时间和应交的费用。 二、算法说明 1.数据结构说明 (1)用到两个堆栈:一个为车场栈;另一个为临时栈temp typedef struct NODE{ CarNode *stack[MAX+1]; int top; }SeqStackCar; /*模拟车场*/ 一个队列结构,存储便道车辆信息: typedef struct Node{ QueueNode *head; QueueNode *rear; }LinkQueueCar; /*模拟便道*/ 2.算法说明 (1) 功能模块说明:停车场管理系统含有三个模块,即:车辆到达、离开、列表显示 图1 (2)以模块为单位分析算法 1、"到达"模块:到达时有两种情况,即车场是否满,未满则直接进入停车场;满时,到 便道等待。如图2。 图2 2."离开"模块:离开时,当车库为空时,提示没有车,结束;否则车辆离开。如图3。 图3 3. "显示"模块:显示模块有两个显示选项,即:车场与便道。如图4。 图4 三、测试结果 (一)测试用例(说明:测试用例要合理并且足够,既要有正确用例,也要有错误用例 ,同时检验程序的正确性和强壮性) 1.第一组测试用例 (1)测试输入:停车场的车辆离开,如下表: "服务选择 "车牌号/车位 "到达/离开时间 " "1 "QH058 "15:25 " "1 "AB123 "18:45 " "1 "EA642 "23:15 " "2 "2 "0:30 " "2 "1 "0:65(错误) " (2)测试目的:测试离开方法时间格式控制以及费用计算是否正确。 (3)正确输出:第一次离开的是AB123,应交费3.45元。第二次时,当在输入65时, 应该提示输入错误,重输。 (4)实际输出: (5)错误原因:第一个错误是在计算时,一个数字错了;第二个是没有对时间格式 控制。 (6)当前状态:已改正 2.第二组测试用例 (1)测试输入:连续6辆车到达,如下表: " 服务选 " 车牌号 " 到达时间 " "择 " " " "1 "A8828 "7:56 " "1 "S2296 "8:25 " "1 "WW666 "8:45 " "1 "HK456 "15:50 " "1 "GH999 "12:30 " "1 "DD555 "13:40 " 测试目的:测试到达方法与列表显示方法能否正确完成。 (3)正确输出:先到达的五辆车先进入停车场,最后到达的一辆在便道等候。 (4)实际输出: (5)错误原因:没有作出时间先后的判断,而是先输入先进入。 (6)当前状态:待修改 3.第三组测试用例 (1)测试输入:接上一步输入离开信息,下表: "服务选择"离开车位"离开时间"便道车进入时 " " " " "间 " "2 "3 "13:30 "13:40 " (2)测试目的:测试离开方法功能是否成功以及便道进入车场是否正确。 (3)正确输出:输出3号车位的车辆离开信息清单,便道1号车进入停车场。 (4)实际输出: 错误原因:没有错误。 (6)当前状态:通过 (二)测试结果分析 此停车管理系统基本可能实现一个小的停车场的管理,其"到达"与"离开"方法都相对比 较完整,以及结算清单明了。尽管在时间先后上有出现混乱,但当其用到实际应用时, 那个时间先后就可以避免了。但在输入数据时,要按照严格的格式输入,否则有可能出 现死去或崩溃。若本系统能加上保存功能就更好了,因为一个系统在使用过程中总会关 机等,而此系统的缺点却是没有保存功能,关闭之后就要重新建立了。会慢慢完善。 附录:源代码 ///系统说明:本系统适应于小型停车场,且停车时间在一天之的短期停放停车场。 //在此系统中,车库容量设置为5,便于测

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

STRANGEX-03

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值