内容描述
设有一个可停放 N 辆汽车的狭长停车场 , 只有一个大门供车辆出入 。车辆按到达先后顺序依次从最里面向大门口停放 。如果已放满 N 辆车 , 再来的车辆只能在大门外的便道上等待 一旦有车辆从停车场离开排在便道上的车辆可依次进入停车场 。
停车场中某辆车离开时 ,在它之后进入停车场的车辆必须为它让路退出停车场 ,等该车辆离开后其后车辆依原次序进入停车场 ,每辆汽车在离开时 ,都要依据停留时间交费 ;停在便道上的车辆不收费 ,在便道上某辆汽车进入停车场或离去后 ,其余车辆仍然保持原来次序。
输入
汽车的模拟输入信息格式可以是 : ( 到达 / 离去的标识 , 汽车牌照号码 , 到达 / 离去的时刻) 。 例如 , ( ‘A’,1,5 ) 表示 1 号牌照汽车在时刻 5 到达 , 而 ( ‘D’,5,20 ) 表示 5 号牌照汽车在时刻 20 离去 。 整个程序在输入信息 (‘E’,0,0 ) 时结束 。
输出
要求程序输出每辆车到达后的 停车位置( 停车场或便道上 ) , 以及某辆车离开停车场时应交纳的费用和在停车场内停留的时间 。
运行结果
思路
- 首先我们先阅读一下内容要求,重点是一个狭窄的停车场,而且按照进来顺序停放,车辆离开的时候需要后面的车让路离开停车场再停进来,我们显然可以判断这是一个链式存储结构,我们可以用单链表来表示停车场。
- 我们再看便道,重点是一头进另一头出,我们可以想到便道则是顺序结构——队列。
- 要求中还说了记录时间,我们可以用hashmap,用键值对的形式记录对应的车牌号跟时间。
- 还要考虑以下几种情况
当停车场没停满时: 到达的车直接开进停车场;离开的车直接退出停车场。
当停车场停满时:
①便道有车,到达的车停进便道队尾;离开的车离开停车场,便道在队首的车开进停车场。
②便道无车,到达的车直接停到便道队首;离开的车直接退出停车场。
定义我们要使用的数据结构
定义单链表
需要用到的函数
添加:add(int data)
遍历:traverseList()
删除:deleteNode(int data)
长度:size()
是否为空:isEmpty()
class LinkedList {
private Node first;//定义头节点
private int nItems;//定义单链表中实际的数据的数目
/**
* 初始化
*/
public LinkedList() {
this.first = null;
this.nItems = 0;
}
/**
* 添加头节点
* @param data
*/
public void addFirst(int data) {
//新建节点
Node newNode = new Node(data);
//将新节点的下一个节点指向旧的头节点
newNode.next = first;
//将新节点设为头节点
first = newNode;
nItems ++;
}
/**
* 删除头结点
* @return
*/
public boolean deleteFirst() {
//判断链表是否为空
if(isEmpty()) {
System.out.println("链表为空!");
return false;
}
first = first.next;
nItems --;
return true;
}
/**
* 插入
* @param data
*/
public void add(int data) {
//创建新节点
Node newNode = new Node(data);
//创建要插入节点的位置上原来的节点
Node current = first;
//原来位置为新插入节点
first = newNode;
//新插入节点的下一个为原节点
newNode.next = current;
nItems ++;
}
/**
* 有序链表的插入,这样简单排序就可以用链表来实现,复杂度为O(N)
* @param data
*/
public void add2(int data) {
//创建新节点
Node newNode = new Node(data);
//创建要插入节点之前的节点
Node previous = null;
//创建要插入节点的位置上原来的节点
Node current = first;
//按从小到大的顺序排序
while(current != null && data > current.data) {
previous = current;
current = current.next;
}
if(previous == null) {
first = newNode;
}else {
previous.next = newNode;
}
newNode.next = current;
nItems ++;
}
/**
* 查询某个特定值的节点
* @param data
* @return
*/
public Node findNode(int data) {
//定义一个新节点用于查询
Node current = first;
while(current != null && current.data != data) {
if(current.next == null) {
System.out.println("该节点不存在");
return null;
}
current = current.next;
}
return current;
}
/**
* 删除某个特定值的节点,并返回该节点
* @param data
* @return 删除的节点
*/
public Node deleteNode(int data) {
//定义被删除节点之前的节点
Node previous = null;
//定义被删除的节点
Node current = first;
while(current != null && current.data != data) {
if(current.next == null) {
System.out.println("该节点不存在");
return null;
}
previous = current;
current = current.next;
}
if(previous == null) {
first = first.next;
}else {
previous.next = current.next;
}
nItems --;
return current;
}
/**
* 遍历链表
*/
public void traverseList() {
//定义一个节点用于遍历
Node current = first;
//判断链表是否为空
if(current == null) {
System.out.println("链表为空!");
return;
}
while(current != null) {
System.out.println(current.data);
current = current.next;
}
}
/**
*
* @return 链表的长度
*/
public int size() {
return nItems;
}
/**
* 判断链表是否为空
* @return
*/
public boolean isEmpty() {
return first == null;
}
}
定义节点
class Node{
//指向下一个节点
public Node next;
//数据域
public int data;
public Node(int data) {
this.data = data;
}
}
定义队列
需要用到的函数
添加:insert(int g)
删除:remove()
class Queue {
private int[] queArray;
private int maxSize;
private int front; //队头
private int rear; //队尾
private int nItems;
/**
* 初始化
*/
public Queue(int maxSize) {
this.maxSize = maxSize;
queArray = new int[maxSize];
front = 0;
rear = 0;
nItems = 0;
}
/**
* 在队尾插入
* @param g
*/
public void insert(int g) {
if (rear == maxSize-1) {
rear = -1;
}//
queArray[++rear] = g;
nItems++;
}
/**
* 从队头删除
*/
public void remove() {
int temp = queArray[front++];
if (front==maxSize) {
front = 0;
}
nItems--;
}
/**
* 查看
* @return 查看的元素
*/
public int peekFront() {
// System.out.println(queArray[front]);
return queArray[front];
}
/**
* 判断是否为空
* @return
*/
public boolean isEmpty() {
return nItems == 0;
}
/**
* 判断是否已经满了
* @return
*/
public boolean isFull() {
return nItems == maxSize;
}
/**
*
* @return 队列的大小
*/
public int size() {
return nItems;
}
}
代码实现
public static void main(String[] args) {
//用队列创建便道,设置能停放9999辆车
Queue queue=new Queue(99999999);
//用单链表创建停车场
LinkedList linkedList=new LinkedList();
//用hashmap记录时间
HashMap<Integer,Integer> hashMap=new HashMap<>();
Scanner scanner=new Scanner(System.in);
while (true){
System.out.println("请输入操作A或者D(到达或离开),再输入车牌号,再输入时间");
String s= scanner.next();
if (s.equals("end")){
break;
}
/**
* 车到达
*/
if (s.equals("A")) {
//当停车场没停满时
if (linkedList.size() < 2) {
//车牌号
int n = scanner.nextInt();
//时间
int t = scanner.nextInt();
//进入停车场
linkedList.add(n);
//记录时间
hashMap.put(n, t);
System.out.println("车牌号为"+n+"已到达停车场");
continue;
}
//停车场满了,需要停便道上
else {
//车牌号
int n = scanner.nextInt();
//时间
int t = scanner.nextInt();
//停进便道
queue.insert(n);
System.out.println("车牌号为"+n+"已到达便道");
//这里不需要记录时间
}
}
/**
* 车离开
*/
if (s.equals("D")) {
//停车场没满
if (linkedList.size() < 2) {
//车牌号
int n = scanner.nextInt();
//离开时间
int t = scanner.nextInt();
//这辆车的开始时间
int starttime = hashMap.get(n);
//开走
linkedList.deleteNode(n);
System.out.println("车牌号为" + n + "的停车时间" + ( t-starttime));
}
//停车场满了
else {
//车牌号
int n = scanner.nextInt();
//离开时间
int t = scanner.nextInt();
//这辆车的开始时间
int starttime = hashMap.get(n);
//开走
linkedList.deleteNode(n);
//停车场车开走
System.out.println("车牌号为" + n + "的停车时间" + ( t-starttime));
//如果便道空了,就没有车从便道开进停车场
if (!queue.isEmpty()){
//便道车开走
queue.remove();
//获得车牌号
int car=queue.peekFront();
System.out.println(car+"从便道开进停车场");
//进停车场
linkedList.add(car);
//记录进停车场时间
hashMap.put(car,t);
}}
}
}}
}