电梯系列,自然要从最简单的单电梯场景开始。
1,电梯状态
电梯状态可以分为空闲、开门、上下移动三个状态,为了便于理解,我们可以忽略开门状态。
也就是说,电梯分为空闲状态和移动状态。
2,楼层
一般有2种,一种是1~n层,没有地下,一种是1~n层和-1~-m层,有地下m层。
在不影响核心研究内容的前提下,默认只考虑第一种,1~n层,没有地下。
3,电梯输入
电梯外输入一般有2种,一种是上下按钮,一种是楼层数值按钮。
电梯内输入都是直接按楼层。
4,比较容易想到的控制算法
先来先服务算法(FCFS)、最短寻找时间优先算法(SSTF)、扫描算法(SCAN)
这三个都是和操作系统的调度算法相通的,我就不解释含义了。
先来先服务算法会造成效率很低,最短寻找时间优先算法会造成饥饿等待,都是不可取的。
所以电梯都是基于扫描算法进行优化的。
5,简单扫描算法
如何模拟呢?
可以抽象为2个函数,一个是输入,包括外部输入和内部输入,一个是输出,显示电梯实时状态。
利用多线程,可以实时控制输入和输出函数同时运行。
本来是构思2个输入函数的,因为多线程不熟,避免输入流的麻烦,就合到一起了,用控制字来描述。
每次输入lev和fla,如果fla为0,表示内部输入要去lev楼,如果fla为1,2,3,表示lev楼有乘客按了上下行。
注意:
(1)代码健壮性很弱,需要严格按照预定方式输入。
(2)外部输入的方式是直接覆盖式的,测试的时候需要人工避免一些奇怪的值。
(3)需要人工控制输入时间,并不是一开始就全部把数据粘贴进去
#include <thread>
#include<time.h>
#define LEVEL 6
int flag[LEVEL + 1]; //1到Level层的外部输入,取值为0,1,2,3,其中0表示无乘客,1表示有乘客上行,2表示有乘客下行,3表示既有上行又有下行
int dest[LEVEL + 1]; //目的楼层的记录,取值为0,1,其中0表示不是目的地,1表示是目的地
void input()
{
int lev, fla;
while (cin >> lev >> fla) if (lev > 0 && lev <= LEVEL)
{
if(fla>0 && fla<=3)flag[lev] = fla; //外部输入
else dest[lev] = 1;//内部输入
}
}
void upPull(int loc)//上行接客
{
flag[loc]--;
cout << "上行接客"<<loc<<endl;
}
void downPull(int loc)//下行接客
{
flag[loc] -= 2;
cout << "下行接客" << loc << endl;
}
void push(int loc)//送客
{
dest[loc] = 0;
cout << "送客" << loc << endl;
}
void run()
{
int loc = 1;
while (1)
{
for (loc = 1; loc <= LEVEL; loc++)
{
cout << " 当前楼层" << loc << endl;
if (flag[loc] == 1 || flag[loc] == 3)upPull(loc);
if (dest[loc])push(loc);
Sleep(1000);
}
for (loc = LEVEL; loc>0; loc--)
{
cout << " 当前楼层" << loc << endl;
if (flag[loc] == 2 || flag[loc] == 3)downPull(loc);
if (dest[loc])push(loc);
Sleep(1000);
}
}
}
int main()
{
thread t1(input);
thread t2(run);
t1.join();
t2.join();
return 0;
}
模拟示例:
示例1
示例2