制作背景:课程小作业
修改日期:2022/10/9
编译环境:vscode
作者:二本双非21级小白
/*
渡口系统
创建三个队列----货车/客车/渡轮
过江渡船每次能载十辆车过江
每上四辆客车才能上一辆货车
如果客车不足四辆,货车补上
没有货车,客车补上
*/
知识背景
- 了解顺序表和链表的基本操作,队列:先进先出
- 留出一个数据空间,利用头尾指针通过 "(Q.rear+1)%Qmaxsize==Q.front" 来判断队满
- 利用 "Q.front=(Q.front+1)%Qmaxsize" 来实现加一下移并在到达上限后,归零重置,实现循环,解决假上溢问题
1、头文件宏定义
#include <iostream>
using namespace std;
//顺序循环队列
#define Qmaxsize 20 //流出一个数据空间不写入数据
#define OK 1
#define TRUE 1
#define ERROR 0
#define FALSE 0
#define OVERFLOW -2
typedef char QElemType;
typedef int Status;
2、结构类型和函数声明
typedef struct
{
QElemType *base;//初始化的动态内存空间
int front; //存储对头元素的下标
int rear; //存储对尾元素的下标
int num; //元素个数
}SqQueue;
//SqQueue后面没有带'*'号,既属于普通类型调用时需要用'.'而不是特殊类型使用的'->'
//基础函数
Status InitQueue(SqQueue &Q);
int QueueLength(SqQueue Q);
Status DeQueue(SqQueue &Q,QElemType &e);
Status EnQueue(SqQueue &Q,QElemType e);
QElemType GetHead(SqQueue Q);
//功能函数
Status Swap_bus(SqQueue &bus,SqQueue &boat);
Status Swap_truck(SqQueue &truck,SqQueue &boat);
Status cout_queue(SqQueue &Q);
/*
渡口系统
创建三个队列----货车/客车/渡轮
过江渡船每次能载十辆车过江
每上四辆客车才能上一辆货车
如果客车不足四辆,货车补上
没有货车,客车补上
*/
3、主函数
int main (void)
{
//初始化三个循环顺序队
SqQueue bus,truck,boat;
InitQueue (bus);
InitQueue (truck);
InitQueue (boat);
QElemType m;
-----临时的测试数据
for(int i=0; i<11; i++)
EnQueue(bus,'*');
for(int j=0; j<11; j++)
EnQueue(truck,'#');
///
cout<<"初始客车数量:"; cout_queue(bus);
cout<<"初始货车数量:"; cout_queue(truck);
int count=0;
while((bus.num!=0)||(truck.num!=0))
{
//十辆车来回一趟
while(boat.num<10){
Swap_bus(bus,boat);
Swap_truck(truck,boat);
if((bus.num==0)&&(truck.num==0))
break;
}
count++;
cout<<"第"<<count<<"班"<<endl;
if(bus.num!=0) cout<<"剩余客车数量:";
cout_queue(bus);
if(truck.num!=0) cout<<"剩余客车数量:";
cout_queue(truck);
cout<<"渡轮上的车辆顺序:";
cout_queue(boat);
for(int i=0;i<10;i++)
DeQueue(boat,m); //清空渡轮
}
cout<<"等候排队"<<endl;
system("pause");
return 0;
}
4、功能函数
Status cout_queue(SqQueue &Q)
{
if(Q.front==Q.rear) return ERROR;//判断队列是否为空//判断队列是否为满
int temp=Q.front;
for(int i=0;i<Q.num;i++){
cout<<Q.base[Q.front]; //输出对头元素
Q.front=(Q.front+1)%Qmaxsize; //对头指针下移
}
Q.front=temp; //对头指针回正
cout<<endl;
return OK;
}
Status Swap_truck(SqQueue &truck,SqQueue &boat)
{
QElemType e;
if(truck.num>0){ //有货车
if(boat.num<10){ //渡轮未满时
DeQueue(truck,e); //删出货车队头元素,并保存
EnQueue(boat,e); //将保存的元素插入渡口队尾
}
else{
cout<<"渡轮已满"<<endl;
return ERROR;
}
return OK;
}
return OK;
}
//将一个队列的前四个元素转移到另一个队列
Status Swap_bus(SqQueue &bus,SqQueue &boat)
{
QElemType e;
if(bus.num>=4){ //当客车大于4辆车时
for(int i=0;i<4;i++){
if(boat.num<10){ //渡轮未满时
DeQueue(bus,e); //删出客车队头元素,并保存
EnQueue(boat,e); //将保存的元素插入渡口队尾
}
else{
cout<<"渡轮已满"<<endl;
return ERROR;
}
}
return OK;
}
else{ //客车数量小于4
for(int j=bus.num;j>0;j--){
if(boat.num<10){
DeQueue(bus,e);
EnQueue(boat,e);
}
else{
cout<<"渡轮已满"<<endl;
return ERROR;
}
}
return OK;
}
}
5、功能函数
//队列的初始化
Status InitQueue(SqQueue &Q)
{
Q.base=new QElemType[Qmaxsize]; //为数组分配空间
if(!Q.base) exit(OVERFLOW); //没有内存空间分配失败
Q.front=0;
Q.rear=0;
Q.num=0;
return OK;
}
//求队列的长度
int QueueLength(SqQueue Q)
{
Q.num=(Q.rear-Q.front+Qmaxsize)%Qmaxsize;
return Q.num;
//利用模将Q.rear-Q.front进行绝对值
}
//出队-----删除元素
Status DeQueue(SqQueue &Q,QElemType &e)
{
if(Q.front==Q.rear) return ERROR;//判断队列是否为空
e=Q.base[Q.front]; //保存对头元素
Q.front=(Q.front+1)%Qmaxsize;
Q.num--;
return OK;
}
//入队-----插入元素---解决假上溢问题
Status EnQueue(SqQueue &Q,QElemType e)
{
if((Q.rear+1)%Qmaxsize==Q.front) return ERROR;//判断队列是否为满
Q.base[Q.rear]=e; //新元素插入队尾
Q.rear=(Q.rear+1)%Qmaxsize; //队尾坐标加一
Q.num++;
return OK;
}
//取队头元素
QElemType GetHead(SqQueue Q)
{
if(Q.front!=Q.rear) //队列不为空
return Q.base[Q.front]; //返回队头元素的值
return ERROR;
}
6、编译结果
遇到的难点:
㈠ 在循环顺序列中,如何实现从头指针front开始打印出指定个数和顺序的元素表,参考函数 Status cout_queue(SqQueue &Q);
㈡ 在处理客车与渡轮队列时,如何实现不同情况的判断区分并顺利实现对应的循环,参考函数 Status Swap_bus(SqQueue &bus,SqQueue &boat);
㈢ 在主函数中,如何确定循环结束的条件,并将所有有效结果打印出来,方便后续调试
特别鸣谢,青岛大学王卓老师的课程指导。