问题描述
设有一个可以停放n辆汽车的狭长停车场,它只有一个大门可以供车辆进出。
车辆按到达停车场时间的早晚依次从停车场最里面向大门口处停放(最先到达的第一辆车放在停车场的最里面)。
如果停车场已放满n辆车,则后来的车辆只能在停车场大门外的便道上等待,
一旦停车场内有车开走,则排在便道上的第一辆车就进入停车场。
停车场内如有某辆车要开走,在它之后进入停车场的车都必须先退出停车场为它让路,
待其开出停车场后,这些车辆再依原来的次序进场。
每辆车在离开停车场时,都应根据它在停车场内停留的时间长短交费。
如果停留在便道上的车未进停车场就要离去,允许其离去,不收停车费,并且仍然保持在便道上等待的车辆的次序。
编制程序模拟该停车场的管理。
要求:
若是到达的车辆,输出其在停车场中或者便道中的位置;
若是离去的车辆,则额输出其在停车场中停留的时间和应缴纳的费用。
问题分析
1.停车场中某车的离开必须在其前面的车已经离开之后才行,满足“先进后出”的特性,因此采用栈来模拟停车场。
2.对于指定停车场,其车位相对固定,因此采用顺序栈。
3.从停车场出来为后面的车让路的车也是先出的后进,因此也用栈来模拟。
4.从停车场出来的车数最大不超过停车场的车,因此采用长度等于车场车辆数的顺序栈。
5.便道上的车按照先到先开进车场的原则,满足“先进先出”的特性,因此可以用队列来模拟便道。
6.便道上的车辆数目不固定,因此采用链队列。
7.每组数据应包含:到达还是离去,车辆牌照号码,到达或离去的时刻。
用到了之前写的顺序栈和链队列
实现代码:有详细注释
package queueTest;
import java.util.Scanner;
import java.text.DecimalFormat;
import java.util.GregorianCalendar;
import com.stack.SqStack;
import com.sun.org.apache.xalan.internal.xsltc.dom.SAXImpl.NamespaceWildcardIterator;
public class ParkingLotManagementSystem {
private SqStack S = new SqStack(100);// 存放停车场上的车辆信息,假设停车场只有100个位置
private LinkQueue Q = new LinkQueue();// 存放便道上的车辆信息
private double fee = 2;// 每分钟停车费用
public final static int DEPARTURE = 0;// 标识车辆离开
public final static int ARRIVAL=1;//标识车辆到达
//内部类,用于存放车辆信息
public class CarInfo{
public int state;//车辆状态,到达/离开
public GregorianCalendar arrTime;//到达时间
public GregorianCalendar depTime;//离开时间
public String license;//车牌号
}
//停车场管理,license表示车牌号,action表示车辆的动作,到达或离开
public void parkingManage(String license,String action) throws Exception{
if("arrive".equals(action)){//到达
CarInfo info=new CarInfo();
info.license=license;//记录车牌号
if(S.length()<100){//停车场未满
info.arrTime=(GregorianCalendar)GregorianCalendar.getInstance();//当前时间初始化到达时间
info.state=ARRIVAL;
S.push(info);//进入停车场
System.out.println(info.license+"停放在停车场第"+S.length()+"个位置!");
}
else {//停车场已满
Q.offer(info);//进入便道
System.out.println(info.license+"停放在停车场第"+Q.length()+"个位置!");
}
}
else if("depart".equals(action)){//车辆离开
CarInfo info=null;
int location=0;//用于记录车辆位置
//构造一个新栈存储因车辆离开而导致的其他车辆暂时退出停车场
SqStack S2=new SqStack(S.length());
for(int i=S.length();i>0;i--){
info=(CarInfo)S.pop();
if(info.license.equals(license)){//如果排到了真要出去的车辆
//当前时间初始化离开时间
info.depTime=(GregorianCalendar)GregorianCalendar.getInstance();
info.state=DEPARTURE;
location=i;
break;
}
else
S2.push(info);//其他车辆暂时退出车场
}
while(!S2.isEmpty()){
//其他车辆重新进入车场
S.push(S2.pop());
}
if(location!=0){//停车场内存在指定车牌号的车辆
//计算停放时间,并把毫秒换成分钟
double time=(info.depTime.getTimeInMillis()-info.arrTime.getTimeInMillis())/(1000*60);
DecimalFormat df=new DecimalFormat("0.0");//对double进行格式化保留两位小数
System.out.println(info.license+"停放"+df.format(time)+"分钟,费用为"+df.format(time*fee));
}
if(!Q.isEmpty()){
info=(CarInfo)Q.poll();
info.arrTime=(GregorianCalendar)GregorianCalendar.getInstance();
info.state=ARRIVAL;
S.push(info);
}
}
}
public static void main(String[] args) throws Exception {
ParkingLotManagementSystem plms=new ParkingLotManagementSystem();
for(int i=1;i<=12;i++){
plms.parkingManage(String.valueOf(i), "arrive");
}
Scanner sc=new Scanner(System.in);
System.out.println("请输入车牌号");
String license=sc.next();
System.out.println("arrive or depart??");
String action=sc.next();
plms.parkingManage(license, action);
}
}