基于双端队列的头删、尾插操作,完成普通队列的应用:呼叫中心的离散事件模拟,测试和调试程序。
本程序为双端队列的应用,双端队列相关内容请查看:双端队列的实现
此实验主要是编写双端队列的应用call.cpp:只使用头插尾删或尾插头删完成离散事件模拟。假定我们的程序模拟的是xauat 网上书店的电话接待台接电话(离散事件)的过程。用户在打电话咨询时,先输自己的标识(如姓名或会员号),然后进入排队等待被接听电话。xauat 服务人员会根据该用户在书店已购买书籍的累计消费情况对拨入的电话进行排序。
- 累计消费超过3000 元的为1 类用户,最先得到服务;
- 累计消费不到3000 元、但已满2000 元的2 类用户在没有1 类用户情况下会得到服务;
- 累计消费不满2000 元、但已满1000 元的3 类用户在没有前两类用户情况下会得到服务;
- 累积消费不满1000 元的用户为4 类用户,在没有前三类用户情况下会得到服务。
- 同类用户根据时间先后确定被接听的次序。
这些离散事件事先存入文件sample.txt,程序接收的离散事件需要从sample.txt 进行,因此程序在运行时需要使用输入重定向的方式将标准输入流指定为sample.txt。
该文件格式如下:
首行为整数N,表明文件接下来有N 行离散事件(需要接听的电话)。接下来的N 行对应N 项拨入电话,每行离散事件包含4 项信息,之间使用一个空格隔开。信息格式如下:
<timestamp> <Name> <status> <duration>
<timestamp>
指该电话的拨入时间点,其值为当时所对应的系统时间片编号(从0 开始算起)。
<Name>
指拨入电话的用户姓名(不考虑重名情况),姓名是字符串,中间不允许有空格。
<status>
指该用户的等级,从1 至4,按照上面的叙述,根据累计消费额分成4 类用户。
<duration>
指该离散事件需要持续的时间片长度。
存储离散时间的示例输入文件sample.txt 如下:
3 -------表明下面共有3 行,对应3 通拨入的电话
0 Andrew 1 2 -----表明1 类用户Andrew 在0 时间片拨入电话,需持续2 个时间片(将占用0、1 时间片)
0 Chris 4 1 -------表明4 类用户Chris 在0 时间片拨入电话,需持续1 个时间片
1 Brian 2 1 -------表明2 类用户Brian 在1 时间片拨入电话,需持续1 个时间片
- 我们可以分析上面的数据,首时间片0 号开始时,有两通电话生成,一个是1 类用户Andrew ,一个是4 类用户Chris,则应先接1类用户Andrew 电话,由于其需持续两个时间片,故应占0、1 两个时间片。因此0号时间片中系统应输出有两通电话的信息,同时还要输出开始处理1 类用户Andrew 电话。
- 当1 号时间片开始时,有1 通电话生成,是2 类用户Brian 的电话。因此1 号时间片下,应输出新到的这通电话,由于仍旧在处理Andrew 的电话,所以在这个时间片不再输出开始处理1 类用户Andrew 电话。
- 当2 号时间片开始时,没有电话生成。由于已经完成了1 类用户Andrew 电话,因此服务人员需要接听其他电话,这时系统已有两通正在等待接听的电话,所以按照优先级原则,晚到的2 类用户Brian 的电话需要接听,因此在这个时间片需要输出开始处理2 类用户Brian 电话。该电话时长为一个时间单元。
- 当3 号时间片开始时,没有电话生成。由于已经完成了2 类用户Brian 电话,因此服务人员需要接听其他电话, 这时系统仅有1通正在等待接听的电话,4 类用户Chris 的电话被接听,因此在这个时间片需要输出开始处理4 类用户Chris电话。该电话时长为一个时间单元。
- 当4 号时间片开始时,没有电话生成。也没有其他需要接听的电话,所以该时间片不需要输处其他信息。系 统模拟也结束了。
为清楚起见,在每一时间片开始,系统都提示如下信息:
Starting tick #<tick>
这里的表示时间片编号,从0 开始。某人电话生成时,输出格式如下:
Call from <Name> a Level<status> member
开始处理某人电话时,输出格式如下:
Answering call from <Name>
这里的<Name>
、<status>
与前面一致。
对于上面的存储离散时间的示例输入文件sample.txt,程序运行后应输出如下信息:
Starting tick #0
Call from Andrew a Level1 member
Call from Chris a Level4 member
Answering call from Andrew
Starting tick #1
Call from Brian a Level2 member
Starting tick #2
Answering call from Brian
Starting tick #3
Answering call from Chris
Starting tick #4 <—注意系统运行到时间片4,打印完时间片信息后,发现已处理完所有电话,退出编写程序,按照上述要求完成离散事件的模拟任务。实现完后,可以变动sample.txt 内容执行程序,检验程序功能是否满足上面的要求,运行正常。
来看一下流程图:
以下是实现代码:
其中Dlist来自于:双端队列
#include<fstream>
#include<string>
#include"Dlist.h"
struct caller {
int timestep;
string name;
int status;
int duration;
};
Dlist<caller> total;
Dlist<caller> lv1, lv2, lv3, lv4;
void sortlv(caller *call){//用于向不同等级的用户队列插值
switch (call->status) {
case 1:
lv1.insertBack(call);
break;
case 2:
lv2.insertBack(call);
break;
case 3:
lv3.insertBack(call);
break;
case 4:
lv4.insertBack(call);
break;
}
}
int main() {
ifstream infile;
infile.open("sample.txt");
if (!infile)
cout << "error! This file not opened!";
int num;
infile >> num;
for (int i = 0; i < num; i++) {
caller *call = new caller;
infile >> call->timestep;
infile >> call->name;
infile >> call->status;
infile >> call->duration;
total.insertBack(call);
}
bool haveCaller=true;
int step=0,servingTime=0;
while (haveCaller) {
cout << "Starting tick #" << step<<endl;
while (!total.isEmpty()) {
caller *c = new caller;
c = total.removeFront();
if (c->timestep == step) {
cout <<"Call from "<<c->name<<" a Level"<< c->status <<" member. "<< endl;
sortlv(c);
}
else {
total.insertFront(c);
break;
}
}
if (servingTime==0) {
if (!lv1.isEmpty()) {
caller *c = new caller;
c = lv1.removeFront();
servingTime = c->duration;
cout << "Answering call from " << c->name<<endl;
}
else if (!lv2.isEmpty()) {
caller *c = new caller;
c = lv2.removeFront();
servingTime = c->duration;
cout << "Answering call from " << c->name << endl;
}else if(!lv3.isEmpty()) {
caller *c = new caller;
c = lv3.removeFront();
servingTime = c->duration;
cout << "Answering call from " << c->name << endl;
}
else if (!lv4.isEmpty()) {
caller *c = new caller;
c = lv4.removeFront();
servingTime = c->duration;
cout << "Answering call from " << c->name << endl;
}
}
if (servingTime==0&&total.isEmpty() && lv1.isEmpty() && lv2.isEmpty() && lv3.isEmpty() && lv4.isEmpty()) {
haveCaller = false;
break;
}
step++;
servingTime--;
}
system("pause");
}
看下运行结果: