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 &current){
landingRequests++;
feedback result;
if (landingQueue.size() < limit){
result = success;
landingQueue.push(current);
}
else{
result = fail;
landingRejected++;
}
return result;
}
feedback CanTakeoff(const Plane &current){
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

来源:https://billc.io/2019/03/airport-simulation/

Airport Simulation (数据结构与算法 – 队列 / Queue 的应用)的更多相关文章

  1. [数据结构与算法]队列Queue 的多种实现

    声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...

  2. javascript数据结构与算法---队列

    javascript数据结构与算法---队列 队列是一种列表,不同的是队列只能在队尾插入元素,在队首删除元素.队列用于存储按顺序排列的数据,先进先出,这点和栈不一样(后入先出).在栈中,最后入栈的元素 ...

  3. JavaScript数据结构与算法-队列练习

    队列的实现 // 队列类 function Deque () { this.dataStore = []; this.enqueueFront = enqueueFront; this.enqueue ...

  4. python数据结构与算法——队列

    队列结构可以使用数组来模拟,只需要设定头和尾的两个标记 参考自<啊哈> # 按书中的代码会出现索引越界的问题(书中申请了超量的空间) # 尝试令tai初始为len(q)-1则不会出错但少了 ...

  5. 每周一练 之 数据结构与算法(Queue)

    这是第二周的练习题,这里补充下咯,五一节马上就要到了,自己的计划先安排上了,开发一个有趣的玩意儿. 下面是之前分享的链接: 1.每周一练 之 数据结构与算法(Stack) 2.每周一练 之 数据结构与 ...

  6. C语言- 基础数据结构和算法 - 队列的顺序存储

    听黑马程序员教程<基础数据结构和算法 (C版本)>, 照着老师所讲抄的, 视频地址https://www.bilibili.com/video/BV1vE411f7Jh?p=1 喜欢的朋友 ...

  7. JS数据结构与算法-队列结构

    队列结构 一.认识队列 受限的线性结构: 我们已经学习了一种受限的线性结构:栈结构. 并且已经知道这种受限的数据结构对于解决某些特定问题,会有特别的 效果. 下面,我们再来学习另外一个受限的数据结构: ...

  8. JavaScript数据结构和算法----队列

    前言 队列和栈很像,只是用了不同的原则.队列是遵循先进先出(FIFO)原则的一组有序的的项,队列在尾部添加新元素,从顶部移除元素.最新添加的元素必须必须排队在队列的,末尾.可以想象食堂排队买饭的样子. ...

  9. js数据结构与算法——队列

    <script> //创建一个队列 function Queue(){ let items = []; //向队尾添加一个新的项 this.enqueue = function(eleme ...

随机推荐

  1. 测试误区《二》 python逻辑运算和关系运算优先级

    关系运算 关系运算就是对2个对象进行比较,通过比较符判断进行比较,有6种方式. x > y 大于 x >= y 大于等于 x < y 小于 x <= y 小于等于 x = y ...

  2. 判断两个数组是否相似 (arraysSimilar)

    题目 解答 思路 具体实现代码 总结 题目 题目来自 慕课网 JavaScript 深入浅出 1-6 编程练习 请在 index.html 文件中,编写 arraysSimilar 函数,实现判断传入 ...

  3. Nginx笔记总结十九:nginx + fancy实现漂亮的索引目录

    编译:./configure --prefix=/usr/local/nginx --add-module=../ngx-fancyindex-master 配置: location / { fanc ...

  4. POJ 2553 The Bottom of a Graph Tarjan找环缩点(题解解释输入)

    Description We will use the following (standard) definitions from graph theory. Let V be a nonempty ...

  5. python标准库-builtin 模块之compile,execfile

    eval函数仅仅允许执行简单的表达式.对于更大的代码块时,使用compile和exec函数. 例子:使用 compile函数验证语法 NAME = "script.py" BODY ...

  6. html解析过程

    Web页面运行在各种各样的浏览器当中,浏览器载入.渲染页面的速度直接影响着用户体验 简单地说,页面渲染就是浏览器将html代码根据CSS定义的规则显示在浏览器窗口中的这个过程.先来大致了解一下浏览器都 ...

  7. Struts2获取request的几种方式汇总

    Struts2获取request三种方法 struts2里面有三种方法可以获取request,最好使用ServletRequestAware接口通过IOC机制注入Request对象. 在Action中 ...

  8. iPhone 8价格狂跌:是国产手机的胜利,还是苹果的黄昏

    ​ 8价格狂跌:是国产手机的胜利,还是苹果的黄昏" title="iPhone 8价格狂跌:是国产手机的胜利,还是苹果的黄昏"> ​   其实呢,这年头发布新款智能 ...

  9. 从5个经典工作开始看语义SLAM

    本文试图概括Semantic SLAM的主要思路和近年工作,⻓期更新.但因水平有限,若有错漏,感谢指正. (更好的公式显示效果,可关注文章底部的公众号) Semantic SLAM 简介 至今为止,主 ...

  10. CountDownLatch源码探究 (JDK 1.8)

    CountDownLatch能够实现让线程等待某个计数器倒数到零的功能,之前对它的了解也仅仅是简单的使用,对于其内部如何实现线程等待却不是很了解,最好的办法就是通过看源码来了解底层的实现细节.Coun ...