Airport Simulation (数据结构与算法 – 队列 / Queue 的应用)
Airport Simulation 是数据结构与算法教材中用于演示Queue的一个小程序(大多数教师似乎会跳过这个练习)。主程序会通过输入总的运行时间、队列里可以等待的最多飞机数量,平均每个时间单元到来的飞机和离开的飞机(提供泊松分布的均值生成随机数)。
运行效果
程序的结构不算复杂,利用Runaway类来封装两个landing和takeoff队列,处理飞机的请求和行为;Plane类来封装飞机的状态和信息,以及在受到指令时输出信息到控制台。只是教材里的讲述有些分散,运行效果也由于输出太多而显得凌乱无比。练习布置许久之后也是一直没有找到一整块时间写完这个练习。这里是前几天完成的一个经过输出优化后的程序,格式比较易于观测。
该程序应在Linux或macOS下编译。在Windows下编译由于不支持彩色输出会出现一些奇怪的转移序列,sleep函数和usleep函数也应当用windows.h中提供的方法实现。
main.cpp和Random.h的源代码如下。其中Random.h用于提供泊松分布的随机数生成,参考自CSDN。
你可以在这里直接下载:https://billc.io/cloud/index.php/s/FeLekECBFKb6GkF
main.cpp:
#include <iostream>
#include <queue>
#include <unistd.h>
#include "Random.h"
using namespace std;
typedef int feedback;
const int success = ;
const int fail = ;
const int USPEED_SHORT = ;
const int USPEED_LONG = ;
enum flightStatus{
null,
toLand,
toTakeoff
};
enum runawayAct{
idle,
letTakeoff,
letLand
};
string percentage(int A, int B){
char *temp = new char[];
sprintf(temp, "%3.2f%%", (double)A / (double)B * );
string output = temp;
return output;
}
class Plane{
private:
int ID;
int comingTime;
flightStatus status;
public:
Plane(){
ID = -;
comingTime = -;
status = null;
}
Plane(int _ID, int _comingTime, flightStatus _status){
usleep(USPEED_SHORT);
ID = _ID;
comingTime = _comingTime;
status = _status;
cout << "[PLANE MESSAGE] Plane NO." << ID << " is applying to " << ((status == toLand) ? "land " : "take off ") << endl;
}
feedback land(int currentTime){
usleep(USPEED_LONG);
cout << "\033[42m[PLANE MESSAGE] Plane NO." << ID << " has landed safely.\033[0m" << endl
<< " Waiting time before landing: " << currentTime - comingTime << "." << endl;
}
feedback takeoff(int currentTime){
usleep(USPEED_LONG);
cout << "\033[42m[PLANE MESSAGE] Plane NO." << ID << " has taken off.\033[0m" << endl
<< " Waiting time before taking off: " << currentTime - comingTime << "." << endl;
}
feedback reject(int currentTime){
usleep(USPEED_LONG);
if(status == toLand){
cout << "\033[41m[AIRPORT MESSAGE] Plane NO." << ID << "'s landing request is rejected.\033[0m" << endl
<< " It has been directed to other airports." << endl;
}
else{
cout << "\033[41m[AIRPORT MESSAGE] Plane NO." << ID << " 's taking off request is rejected.\033[0m" << endl
<< " This flight is delayed." << endl;
}
}
int getTime(){
return comingTime;
}
}; class Runaway{
private:
queue<Plane> landingQueue;
queue<Plane> takeoffQueue;
int limit;
runawayAct act;
int landingRequests;
int landingAccepted;
int landingRejected;
int takeoffRequests;
int takeoffAccepted;
int takeoffRejected;
int idleUnit;
int landingWaitedTime;
int takeoffWaitedTime; public:
Runaway(int _limit){
limit = _limit;
landingRequests = ;
landingAccepted = ;
takeoffRequests = ;
takeoffAccepted = ;
takeoffRejected = ;
idleUnit = ;
landingWaitedTime = ;
takeoffWaitedTime = ;
}
feedback CanLand(const Plane ¤t){
landingRequests++;
feedback result;
if (landingQueue.size() < limit){
result = success;
landingQueue.push(current);
}
else{
result = fail;
landingRejected++;
}
return result;
}
feedback CanTakeoff(const Plane ¤t){
takeoffRequests++;
feedback result;
if (takeoffQueue.size() < limit){
result = success;
takeoffQueue.push(current);
}
else{
result = fail;
takeoffRejected++;
}
return result;
}
runawayAct Act(int timeNow, Plane &moving){
runawayAct result;
if (!landingQueue.empty()){
landingAccepted++;
moving = landingQueue.front();
landingWaitedTime += timeNow - moving.getTime();
landingQueue.pop();
return letLand;
}
else if(!takeoffQueue.empty()){
takeoffAccepted++;
moving = takeoffQueue.front();
takeoffWaitedTime += timeNow - moving.getTime();
takeoffQueue.pop();
return letTakeoff;
}
else{
idleUnit++;
return idle;
}
}
void SumUp(int simulationTime){
cout << endl;
cout << "\033[36m=============== SIMULATION RESULTS ===============\033[0m" << endl
<< "\033[5;3mCalculating...\033[0m" << endl;
sleep();
cout
<< "\033[1ATotal simulation time: " << simulationTime << endl
<< "Total flights simulated: " << landingRequests + takeoffRequests << endl
<< "Total flights required to land: " << landingRequests << endl
<< "Landing request accepted: " << landingAccepted << endl
<< "Landing request rejected: " << landingRejected << endl
<< "Total flights required to take off: " << takeoffRequests << endl
<< "Taking off request accepted: " << takeoffAccepted << endl
<< "Taking off request rejected: " << takeoffRejected << endl
<< "Flights still left in landing queue: " << landingQueue.size() << endl
<< "Flights still left in taking off queue: " << takeoffQueue.size() << endl
<< "Average waiting time in landing queue: " << (float)landingWaitedTime / (float)landingAccepted << endl
<< "Average waiting time in taking off queue: " << (float)takeoffWaitedTime / (float)takeoffAccepted << endl
<< "Average observing time for landing flights: " << (float)landingRequests / (float)simulationTime << endl
<< "Average observing time for taking off flights: " << (float)takeoffRequests / (float)simulationTime << endl
<< "Ratio for successfully landed flights: " << percentage(landingAccepted, landingRequests) << endl
<< "Ratio for successfully took off flights: " << percentage(landingAccepted, landingRequests) << endl
<< "Ratio of runaway idle time: " << percentage(idleUnit, simulationTime) << endl
<< endl
<< "\033[3;2mSimulation finished.\033[0m" << endl;
}
};
void initilize(int &totalTime, int &queueLimit, float &arrivingRate, float &departureRate){
cout << "\033[2J\033[0;0H";
cout << "Welcome to the \033[46mAIRPORT SIMULATOR\033[0m." << endl;
sleep();
cout << "\033[36mPlease enter how many time units you will simulate:\033[0m\n"
<< flush;
cin >> totalTime;
cout << "\033[36mHow many flights can be waiting to land or takeoff?\033[0m" << endl
<< flush;
cin >> queueLimit;
cout << "\033[36mWhat is the expected arriving flights per unit time?\033[0m" << endl
<< flush;
cin >> arrivingRate;
cout << "\033[36mWhat is the expected departing flights per unit time?\033[0m" << endl
<< flush;
cin >> departureRate;
} int main(){
START:
float arrivingRate, departureRate;
int totalTime, queueLimit;
initilize(totalTime, queueLimit, arrivingRate, departureRate);
int currentTime;
int planeID = ;
Random randomSeed;
Runaway airport(queueLimit);
for (currentTime = ; currentTime < totalTime; currentTime++){
cout << "\033[2m----- Current excution time: " << currentTime << " -----\033[0m" << endl;
int comingPerUnit = randomSeed.poisson(arrivingRate);
for (int num = ; num < comingPerUnit; num++, planeID++){
Plane currentPlane(planeID, currentTime, toLand);
if(airport.CanLand(currentPlane)==fail){
currentPlane.reject(currentTime);
}
}
int departingPerUnit = randomSeed.poisson(departureRate);
for (int num = ; num < departingPerUnit; num++, planeID++){
Plane currentPlane(planeID, currentTime, toTakeoff);
if(airport.CanTakeoff(currentPlane)==fail){
currentPlane.reject(currentTime);
}
}
Plane movingPlane;
switch (airport.Act(currentTime, movingPlane)){
case letLand:
movingPlane.land(currentTime);
break;
case letTakeoff:
movingPlane.takeoff(currentTime);
break;
case idle:
cout << "\033[46m[AIRPORT MESSAGE]: Runaway is idle.\033[0m" << endl;
break;
}
}
airport.SumUp(totalTime);
char ch;
cout << "\033[36mDo you want to initialize another simulation? \n([R] or [r] to restart, any other key to exit.)\033[0m" << endl;
while(cin.get()!='\n')
;
if (toupper(ch = cin.get()) == 'R')
goto START;
return ;
}
Random.h:
#ifndef RANDOM_H_INCLUDED
#define RANDOM_H_INCLUDED #include <iostream>
#include <time.h>
#include <limits.h>
#include <math.h> using namespace std; class Random
{ public:
Random(bool pseudo = true);
double random_real();
int random_integer(int low, int high);
int poisson(double mean); private:
int reseed(); // Re-randomize the seed.
int seed, multiplier, add_on; // constants for use in arithmetic operations
};
#include "Random.h" Random::Random(bool pseudo)
/*Post: The values of seed, add_on, and multiplier are
initialized. The seed is initialized randomly only if pseudo == false.
*/
{
if (pseudo)
seed = ;
else
seed = time(NULL) % INT_MAX;
multiplier = ; // 斜率
add_on = ; // 位移
} int Random::reseed()
//Post: The seed is replaced by a pseudorandom successor.
{
seed = seed * multiplier + add_on;
return seed;
} double Random::random_real()
/*Post: A random real number between 0 and 1 is returned.*/
{
double max = INT_MAX + 1.0; //INT_MAX = (2)31 -1
double temp = reseed();
if (temp < )
temp = temp + max;
return temp / max;
} int Random::random_integer(int low, int high) // 这个函数在泊松分布中没有用到
{
double max = INT_MAX + 1.0; //INT_MAX = (2)31 -1
double temp = reseed();
if (temp < )
temp = temp + max;
return (int)(temp / (max / (high - low + 1.0) + low)); // 返回整数,且有规定范围
} int Random::poisson(double mean) // 泊松分布的实现
{
double x = -;
double u;
double log1, log2;
log1 = ;
log2 = -mean;
do
{
u = random_real();
log1 += log(u);
x++;
} while (log1 >= log2);
return x;
}
#endif // RANDOM_H_INCLUDED
Airport Simulation (数据结构与算法 – 队列 / Queue 的应用)的更多相关文章
- [数据结构与算法]队列Queue 的多种实现
声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...
- javascript数据结构与算法---队列
javascript数据结构与算法---队列 队列是一种列表,不同的是队列只能在队尾插入元素,在队首删除元素.队列用于存储按顺序排列的数据,先进先出,这点和栈不一样(后入先出).在栈中,最后入栈的元素 ...
- JavaScript数据结构与算法-队列练习
队列的实现 // 队列类 function Deque () { this.dataStore = []; this.enqueueFront = enqueueFront; this.enqueue ...
- python数据结构与算法——队列
队列结构可以使用数组来模拟,只需要设定头和尾的两个标记 参考自<啊哈> # 按书中的代码会出现索引越界的问题(书中申请了超量的空间) # 尝试令tai初始为len(q)-1则不会出错但少了 ...
- 每周一练 之 数据结构与算法(Queue)
这是第二周的练习题,这里补充下咯,五一节马上就要到了,自己的计划先安排上了,开发一个有趣的玩意儿. 下面是之前分享的链接: 1.每周一练 之 数据结构与算法(Stack) 2.每周一练 之 数据结构与 ...
- C语言- 基础数据结构和算法 - 队列的顺序存储
听黑马程序员教程<基础数据结构和算法 (C版本)>, 照着老师所讲抄的, 视频地址https://www.bilibili.com/video/BV1vE411f7Jh?p=1 喜欢的朋友 ...
- JS数据结构与算法-队列结构
队列结构 一.认识队列 受限的线性结构: 我们已经学习了一种受限的线性结构:栈结构. 并且已经知道这种受限的数据结构对于解决某些特定问题,会有特别的 效果. 下面,我们再来学习另外一个受限的数据结构: ...
- JavaScript数据结构和算法----队列
前言 队列和栈很像,只是用了不同的原则.队列是遵循先进先出(FIFO)原则的一组有序的的项,队列在尾部添加新元素,从顶部移除元素.最新添加的元素必须必须排队在队列的,末尾.可以想象食堂排队买饭的样子. ...
- js数据结构与算法——队列
<script> //创建一个队列 function Queue(){ let items = []; //向队尾添加一个新的项 this.enqueue = function(eleme ...
随机推荐
- win10安装3DSMAX失败,怎么强力卸载删除注册表并重新安装
一些搞设计的朋友在win10系统下安装3DSMAX失败或提示已安装,也有时候想重新安装3DSMAX的时候会出现本电脑windows系统已安装3DSMAX,你要是不留意直接安装3DSMAX,只会安装3D ...
- 位移&二进制转换&原码&反码&补码
<< 左移 按二进制形式把所有的数字向左移动对应的位数,高位移出(舍弃),低位的空位补零. 格式 需要移位的数字 << 移位的次数 计算过程 1. 按二进制形式把所有的数字向左 ...
- Holer一款局域网服务器代理到公网的内网映射工具
Holer简介 Holer是一个将局域网服务器代理到公网的内网映射工具,支持转发基于TCP协议的报文. 相关链接 开源地址:https://github.com/Wisdom-Projects/hol ...
- C++如何保留2位小数输出
cout<<setiosflags(ios::);//需要头文件#include <iomanip> 然后再输出实数类型变量即可以保留2位小数输出了,当然你要保留三位小数,se ...
- 网络爬虫url跳转代码
from bs4 import BeautifulSoup from urllib.request import urlopen import re import random base_url = ...
- Redis-输入输出缓冲区
一.client list id:客户端连接的唯一标识,这个id是随着Redis的连接自增的,重启Redis后会重置为0addr:客户端连接的ip和端口fd:socket的文件描述符,与lsof命令结 ...
- springboot利用swagger构建api文档
前言 Swagger 是一款RESTFUL接口的文档在线自动生成+功能测试功能软件.本文简单介绍了在项目中集成swagger的方法和一些常见问题.如果想深入分析项目源码,了解更多内容,见参考资料. S ...
- android使用giflib加载gif
转载请标明出处:https:////www.cnblogs.com/tangZH/p/12356915.html 背景不多说,反正ndk加载gif比java上加载gif好很多很多,主要体现在内存占用与 ...
- 线程sleep,wait,notify,join,yield方法解析
线程的五种状态 线程从创建到销毁一般分为五种状态,如下图: 1) 新建 当用new关键字创建一个线程时,就是新建状态. 2) 就绪 调用了 start 方法之后,线程就进入了就绪阶段.此时,线程不会立 ...
- linux学习--2.文件管理的基本命令
文件的基本操作 前言: 看完这篇图文我应该能保证读者在Linux系统下对文件的操作能跟用Windows环境下一样流畅吧,好了下面正文 正文: 基础知识: linux里共有以下几类文件,分别为目录(di ...