本文完整实现了基于栈+队列的停车场管理系统,包含详细源码和逐行解析,特别适合复习数据结构与算法综合应用
一、系统设计思路
1. 数据结构设计
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define MAX_SIZE 5 // 停车场容量(可修改)
#define PRICE_PER_MIN 0.2 // 每分钟费用
// 车辆信息结构体
typedef struct {
char license[10]; // 车牌号
time_t enter_time; // 进入时间戳
time_t exit_time; // 离开时间戳
} CarInfo;
// 栈结构(停车场)
typedef struct {
CarInfo data[MAX_SIZE];
int top; // 栈顶指针
} ParkingStack;
// 队列节点(便道)
typedef struct QueueNode {
CarInfo car;
struct QueueNode* next;
} QueueNode;
// 队列结构(便道)
typedef struct {
QueueNode* front; // 队首
QueueNode* rear; // 队尾
int count; // 车辆计数
} WaitingQueue;
2. 核心算法
- 栈管理停车场:后进先出(LIFO)模拟车辆停放顺序
- 队列管理便道:先进先出(FIFO)保证公平等待
- 让车处理:目标车离开时,后方车辆先退栈暂存,再按原序压回
3. 功能模块
- 车辆到达处理
- 车辆离开计费
- 实时显示停车场/便道状态
- 时间自动记录与计算
二、完整源码(约250行)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define MAX_SIZE 5 // 停车场容量
#define PRICE_PER_MIN 0.2 // 每分钟费用
// 车辆信息
typedef struct {
char license[10]; // 车牌号
time_t enter_time; // 进入时间戳
time_t exit_time; // 离开时间戳
} CarInfo;
// 栈结构(停车场)
typedef struct {
CarInfo data[MAX_SIZE];
int top;
} ParkingStack;
// 队列节点(便道)
typedef struct QueueNode {
CarInfo car;
struct QueueNode* next;
} QueueNode;
// 队列结构(便道)
typedef struct {
QueueNode* front;
QueueNode* rear;
int count;
} WaitingQueue;
// 初始化停车场栈
void initParking(ParkingStack* ps) {
ps->top = -1;
}
// 初始化等待队列
void initQueue(WaitingQueue* wq) {
wq->front = wq->rear = NULL;
wq->count = 0;
}
// 车辆进入便道
void enqueue(WaitingQueue* wq, CarInfo car) {
QueueNode* newNode = (QueueNode*)malloc(sizeof(QueueNode));
newNode->car = car;
newNode->next = NULL;
if (wq->rear == NULL) {
wq->front = wq->rear = newNode;
} else {
wq->rear->next = newNode;
wq->rear = newNode;
}
wq->count++;
printf("车辆 %s 进入便道等待,当前位置:%d\n", car.license, wq->count);
}
// 便道车辆进入停车场
CarInfo dequeue(WaitingQueue* wq) {
if (wq->front == NULL) {
CarInfo empty = {"", 0, 0};
return empty;
}
QueueNode* temp = wq->front;
CarInfo car = temp->car;
wq->front = wq->front->next;
if (wq->front == NULL) {
wq->rear = NULL;
}
free(temp);
wq->count--;
return car;
}
// 车辆进入停车场
void push(ParkingStack* ps, CarInfo car) {
if (ps->top == MAX_SIZE - 1) {
printf("停车场已满!\n");
return;
}
ps->data[++ps->top] = car;
printf("车辆 %s 进入停车场,车位:%d\n", car.license, ps->top + 1);
}
// 车辆离开停车场
CarInfo pop(ParkingStack* ps) {
if (ps->top == -1) {
CarInfo empty = {"", 0, 0};
return empty;
}
return ps->data[ps->top--];
}
// 显示当前状态
void display(ParkingStack* ps, WaitingQueue* wq) {
printf("\n===== 停车场状态 =====\n");
if (ps->top == -1) {
printf("停车场为空\n");
} else {
for (int i = 0; i <= ps->top; i++) {
printf("车位 %d: %s (进入时间: %s",
i + 1,
ps->data[i].license,
ctime(&ps->data[i].enter_time));
}
}
printf("\n===== 便道状态 =====\n");
if (wq->count == 0) {
printf("便道为空\n");
} else {
QueueNode* current = wq->front;
int pos = 1;
while (current != NULL) {
printf("等待 %d: %s\n", pos++, current->car.license);
current = current->next;
}
}
printf("\n");
}
// 处理车辆离开
void handleExit(ParkingStack* ps, WaitingQueue* wq, char* license) {
ParkingStack temp; // 临时栈存放让路车辆
initParking(&temp);
int found = 0;
CarInfo exitCar;
// 在停车场中查找目标车辆
while (ps->top != -1) {
CarInfo car = pop(ps);
if (strcmp(car.license, license) == 0) {
found = 1;
exitCar = car;
break;
}
push(&temp, car); // 让路车辆压入临时栈
}
// 未找到车辆
if (!found) {
printf("未找到车牌为 %s 的车辆\n", license);
// 还原停车场
while (temp.top != -1) {
CarInfo car = pop(&temp);
push(ps, car);
}
return;
}
// 计算费用
exitCar.exit_time = time(NULL);
double duration = difftime(exitCar.exit_time, exitCar.enter_time) / 60; // 分钟
double fee = duration * PRICE_PER_MIN;
printf("车辆 %s 离开,停留时间: %.1f分钟,费用: ¥%.2f\n",
license, duration, fee);
// 将临时栈中的车辆移回停车场
while (temp.top != -1) {
CarInfo car = pop(&temp);
push(ps, car);
}
// 检查便道并放行一辆车
if (wq->count > 0) {
CarInfo newCar = dequeue(wq);
newCar.enter_time = time(NULL);
push(ps, newCar);
}
}
int main() {
ParkingStack parking;
WaitingQueue queue;
initParking(&parking);
initQueue(&queue);
int choice;
char license[10];
while (1) {
printf("\n===== 停车场管理系统 =====\n");
printf("1. 车辆到达\n");
printf("2. 车辆离开\n");
printf("3. 显示状态\n");
printf("4. 退出系统\n");
printf("请选择操作: ");
scanf("%d", &choice);
switch (choice) {
case 1: // 车辆到达
printf("请输入车牌号: ");
scanf("%s", license);
CarInfo newCar;
strcpy(newCar.license, license);
newCar.enter_time = time(NULL);
if (parking.top < MAX_SIZE - 1) {
push(&parking, newCar);
} else {
enqueue(&queue, newCar);
}
break;
case 2: // 车辆离开
printf("请输入离开车牌号: ");
scanf("%s", license);
handleExit(&parking, &queue, license);
break;
case 3: // 显示状态
display(&parking, &queue);
break;
case 4: // 退出系统
printf("系统已退出\n");
exit(0);
default:
printf("无效选择,请重新输入\n");
}
}
return 0;
}
三、关键代码解析
1. 数据结构核心
typedef struct {
CarInfo data[MAX_SIZE]; // 连续内存存储车辆
int top; // 栈顶指针(-1表示空)
} ParkingStack;
- 顺序栈:数组存储实现高效随机访问,
top
指向最新车辆 - 时间复杂度:入栈/出栈操作仅需O
2. 让路算法实现
while (ps->top != -1) {
CarInfo car = pop(ps); // 弹出顶层车辆
if (匹配目标车牌) {
found = 1; // 标记找到目标
break;
}
push(&temp, car); // 非目标车压入临时栈
}
- 栈操作模拟:后入车辆必须先移出(后进先出原则)
- 暂存机制:用临时栈保持让路车辆顺序,移回时顺序不变
3. 便道队列管理
typedef struct QueueNode {
CarInfo car;
struct QueueNode* next; // 链式存储
} QueueNode;
4. 时间自动处理
time_t enter_time = time(NULL); // 获取当前时间戳
double duration = difftime(exit_time, enter_time) / 60; // 计算分钟数
- 时间戳记录:精确到秒的停留时间计算
- difftime函数:跨平台安全计算时间差
四、复习要点总结
知识点 | 实现要点 | 应用场景 |
---|---|---|
栈(Stack) | 数组存储+top指针 | 停车场车辆管理(后进先出) |
队列(Queue) | 链表实现+头尾指针 | 便道等待车辆(先进先出) |
时间处理 | time_t + difftime() | 停车计时与费用计算 |
内存管理 | malloc/free操作 | 动态管理队列节点 |
算法逻辑 | 临时栈让路机制 | 车辆离开时的通道处理 |
关键学习方向:
- 栈与队列的混合使用:停车场满时自动切换数据结构
- 时间函数实战应用:理解系统时间戳与差值计算
- 链式存储优势:队列长度动态变化不受数组限制
- 数据持久化扩展:可添加文件保存停车记录(复习fread/fwrite)
系统运行示例:
===== 停车场状态 =====
车位 1: 京A12345 (进入时间: Wed Jun 27 14:30:25 2025)
车位 2: 沪B67890 (进入时间: Wed Jun 27 14:35:12 2025)
===== 便道状态 =====
等待 1: 粤C54321
等待 2: 苏D87654
通过此项目可深入掌握数据结构综合应用与系统级C编程的核心技能。
建议尝试扩展功能:停车记录保存、按小时计费优化、可视化界面等。