离散事件模拟
离散事件模拟
July 10, 2010
/* by SonicRang */
#include <iostream>
#include <stdlib.h>
#include <time.h>
#include <windows.h>
using namespace std;
#define WINDOW 5 //定义服务窗口个数
/* 定义各窗口服务队列 */
typedef struct qnode
{
int arrivetime; //到达时刻
int duration; //处理时长
struct qnode *next;
}Qnode, *Queptr;
typedef struct
{
Qnode *front, *rear;
int length;
}LinkQueue;
/* 定义结束 */
/* 定义一天内所有事件链表 */
typedef struct enode
{
int occurTime, NType; //事件发生时刻,事件类型(0:未发生 非0:已完成)
struct enode *next;
}Enode, *Eptr;
typedef struct
{
Enode *front, *rear;
int eventNum; //事件数
}EventList;
/* 定义结束 */
/* 定义全局变量 */
EventList *eventlist; //事件链表
LinkQueue q[WINDOW + 1]; //窗口队列
Eptr pe, ev; //事件节点
int seed = 300;
int closetime; //银行工作时长
int totaltime; //总时间
int customerNum; //客流量
/* 定义结束 */
/* 插入客户事件到事件链表 */
void InsertEvent(EventList *eventlist, int Time, int Type)
{
Eptr p, q, location;
p = new Enode;
p->occurTime = Time;
p->NType = Type;
eventlist->eventNum++;
q = eventlist->front;
location = NULL;
while (q && (Time > q->occurTime)) //找到插入位置
{
location = q;
q = q->next;
}
if (location == NULL) //找到了空队列插入到队头
{
p->next = eventlist->front;
eventlist->front = p;
}
else //找到了非空队列插入到队尾
{
p->next = q;
location->next = p;
}
if (eventlist->eventNum == 1) //初始化队尾
{
eventlist->rear = p;
}
}
/* 插入完成 */
/* 删除事件链表中的事件 */
void DeletEvent(EventList *ev, Eptr &data)
{
Eptr p;
p = ev->front;
ev->front = p->next;
if (--ev->eventNum<1)
{
ev->rear = ev->front;
}
data = p;
}
/* 删除完成 */
/* 当前客户插入窗口队列 */
void EnQueue(LinkQueue *q, int t1, int t2)
{
Queptr p;
p = new Qnode;
p->arrivetime = t1;
p->duration = t2;
q->length++;
if (q->length == 1) //只有一个元素的队列处理
{
p->next = NULL;
q->front = q->rear = p;
}
else
{
p->next = q->rear->next;
}
q->rear->next = p;
q->rear = p; //重连接队列
}
/* c插入完成 */
/* 当前客户出窗口队列进行处理 */
void DeQueue(LinkQueue *q, Queptr f)
{
Queptr p;
if (q->length>0)
{
f->arrivetime = q->front->arrivetime;
f->duration = q->front->duration;
p = q->front;
q->front = q->front->next;
q->length--;
if (q->length == 0)
q->rear = NULL;
delete (p);
}
}
/* 处理结束 */
/* 找最短队列 */
int Minlength()
{
int min, j, i;
min = q[1].length;
j = 1;
for (i = 2; i <= WINDOW; i++)
if (q[i].length < min)
{
min = q[i].length;
j = i;
}
return j;
}
/* 查询完成 */
/* 初始化银行 */
void Open()
{
int i;
eventlist = new EventList;
pe = new Enode;
pe->occurTime = 0; //初始化发生事件事件
pe->NType = 0;
pe->next = NULL;
eventlist->front = pe; //插入第一个客户到事件表
eventlist->rear = pe;
eventlist->eventNum = 1;
for (i = 1; i < WINDOW + 1; i++) //初始化服务窗口队列为空
{
q[i].front = q[i].rear = NULL;
q[i].length = 0;
}
}
/* 初始化结束 */
/* 客户到达 */
void CustomerArrived()
{
int durtime, intertime, min;
customerNum++; //客流量增加
srand((unsigned)time(NULL));
Sleep(1000);
durtime = 5 + rand() % 31; //产生随机数(当前客户所需的服务时间和下一个用户到达的时间间隔)
intertime = 5 + rand() % 11;
if ((ev->occurTime + intertime) < closetime)
InsertEvent(eventlist, ev->occurTime + intertime, 0); //下一个客户到事件加入事件表
min = Minlength(); //找最短队列
EnQueue(&q[min], ev->occurTime, durtime); //客户加入窗口
cout << "客户于<" << ev->occurTime << ">时刻进入" << min << "号窗口," << "处理了" << durtime << "分钟" << endl;
if (q[min].length == 1)
InsertEvent(eventlist, ev->occurTime + durtime, min); //唯一客户加入离开事件
}
/* 函数结束 */
/* 客户离开 */
void CustomerLeave()
{
int i;
i = ev->NType; //第i号窗的客户离开
Queptr data;
data = new Qnode;
DeQueue(&q[i], data); //删除i号窗口的排头客户
cout << i << "号窗口客户离开" << endl;
totaltime += ev->occurTime - data->arrivetime; //总时间累积
if (q[i].length != 0) //插入离开事件
InsertEvent(eventlist, ev->occurTime + q[i].front->duration, i);
}
/* 函数结束 */
/* 主函数 */
void main()
{
cout << "**************银行模拟系统**************" << endl;
cout << "请输入银行营业时长(分钟):" << endl;
cin >> closetime;
Open(); //初始化银行
while (eventlist->eventNum > 0) //事件非空开始执行
{
DeletEvent(eventlist, ev); //取事件表中的第一个事件节点
if (ev->NType == 0) //处理客户到达事件
CustomerArrived();
else
CustomerLeave(); //处理离开事件
}
cout << "今日客流量:" << customerNum << endl;
cout << "平均处理时间:" << totaltime / customerNum << "分钟" << endl;
system("pause");
}最后更新于