一、题目
详见<数据结构与c语言>(严蔚敏) p65
二、实现
/*****************************************************************
*功 能:模拟银行的业务
*作 者:JarvisChu
*时 间:2010.11.27
*备 注:《数据结构 c语言版》(严蔚敏) p67
******************************************************************/
#include <stdio.h>
#include <malloc.h>
//---------------------------数据结构定义---------------------------------------------
typedef struct Event{ //事件
int OccurTime; //事件发生时间
int NType; //事件类型 0 表示到达事件 1~4表示四个窗口的离开时间
struct Event* next; //指向下一条事件
}Event,ElemType;
typedef struct{ //事件表(按照事件发生时间排序)
Event * pHead;
}EventList;
typedef struct QElemType{ //队列元素
int ArriveTime; //到达时间
int Duration; //办理业务所需时间
struct QElemType* next; //下一个客户信息
}QElemType;
typedef struct{
QElemType* front; //队首
QElemType* rear; //队尾
}Queue;
//--------------------------全局变量定义----------------------------------------------
EventList *ev_list; //事件表
//Event *event; //事件
Queue q[5]; //四个客户队列
int TotalTime; //客户逗留总时间
int CustomerNum; //客户数
int CloseTime;
//--------------------------链表操作------------------------------------------------
//初始化链表
void InitEventList(EventList* el){
el->pHead = (Event *)malloc(sizeof(Event));
el->pHead->next = NULL;
}
//按序插入
void OrderInsertEvent(EventList* el,Event* ev){
Event* pEv = NULL;
pEv = el->pHead->next; //第一个事件
if(pEv == NULL){ //空表
// printf("空表\n");
el->pHead->next = ev;
ev->next = NULL;
// printf("%d\n",el->pHead->next->OccurTime);
//printf("%d\n",pEv->OccurTime);
return;
}
if(pEv->OccurTime > ev->OccurTime){ //该事件小于第一个事件
// printf("小于第一个事件\n");
ev->next = el->pHead->next;
el->pHead->next = ev;
return;
}
while (pEv->next != NULL && (pEv->next->OccurTime < ev->OccurTime)){ //
pEv = pEv->next;
}
if(pEv->next == NULL){ //该事件在表尾
pEv->next = ev;
ev->next = NULL;
return;
}
else{
ev->next = pEv->next;
pEv->next = ev;
return;
}
}
//删除头结点
Event* deleteHead(EventList* el){
Event* del = NULL;
del = el->pHead->next; //表中第一个事件
if(del != NULL){ //表中有事件
el->pHead->next = el->pHead->next->next;
}
return del;
}
//显示节点
void EventDisplay(Event* ev){
printf("OccurTime = %d ,NType = %d \n",ev->OccurTime,ev->NType);
}
//显示事件表
void EventListDisplay(EventList* el){
Event* pEv;
pEv = el->pHead->next; //第一个事件
while(pEv != NULL){ //空表
EventDisplay(pEv);
pEv = pEv->next;
}
}
//--------------------------队列操作------------------------------------------------
//初始化队列
void InitQueue(Queue* qu){
qu->front = qu->rear = (QElemType*)malloc(sizeof(QElemType));
qu->front->next = NULL;
}
//入队
void EnQueue(Queue* qu,QElemType* elem){
// QElemType * tmp;
// tmp = (QElemType*)malloc(sizeof(QElemType));
// tmp->ArriveTime = elem->
elem->next = NULL;
qu->rear->next = elem;
qu->rear =qu->rear->next; //elem;
}
//出队
QElemType* DeQueue(Queue* qu){
QElemType* del= NULL;
if(qu->front == qu->rear) //空队
return NULL;
del = qu->front->next;
qu->front = qu->front->next;
//if(del != NULL){
// qu->front->next = qu->front->next->next;
//}
return del;
}
//队列长度
int NumOfQueue(Queue* qu){
int i = 0;
QElemType* pQE;
if(qu->front == qu->rear) //空队
return 0;
pQE = qu->front->next; //第一个事件
while(pQE != NULL){ //空表
i++;
pQE = pQE->next;
}
return i;
}
//比较大小,返回最小索引
int min(int a,int b,int c,int d){
int i;
int num[4];
int index = 0;
int minnum = a;
num[0] = a;
num[1] = b;
num[2] = c;
num[3] = d;
for(i=0;i<4;i++){
if(minnum > num[i]){
minnum = num[i];
index = i;
}
}
return (++index);
}
//显示队列节点
void QueueElemDisplay(QElemType* elem){
printf("ArriveTime = %d ,Duration = %d \n",elem->ArriveTime,elem->Duration);
}
//显示队列
void QueueDisplay(Queue* qu){
QElemType* pQE;
pQE = qu->front->next; //第一个事件
while(pQE != NULL){ //空表
QueueElemDisplay(pQE);
pQE = pQE->next;
}
}
//--------------------------业务处理--------------------------------------
//银行开门
void OpenForDay(){
int i;
Event* event;
TotalTime = 0;
CustomerNum = 0;
printf(" 银行开始营业\n");
printf("*****************************************\n");
ev_list = (EventList *)malloc(sizeof(EventList));
InitEventList(ev_list); //初始化事件表
for(i=0;i<5;i++) //初始化四个窗口队列
InitQueue(&q[i]);
event = (Event*)malloc(sizeof(Event));
event->OccurTime = 0; //设定第一个客户的到达事件
event->NType = 0;
OrderInsertEvent(ev_list,event);
// EventListDisplay(ev_list);
}
//处理客户到达事件
void CustmerArrived(Event* ev){
int durtime; //本客户处理业务事件
int intertime; //下一个客户将在intertime时间后到
int minQueue;
int occurtime; //事件发生时间
Event* event_in;
Event* event_out;
QElemType* elem;
CustomerNum++;
durtime = rand()%100;
intertime = rand()%100+2;
occurtime = ev->OccurTime;
// printf("客户到达:OccurTime = %d\n",ev->OccurTime);
printf("%-4d时刻:客户到达 ",ev->OccurTime);
elem = (QElemType*)malloc(sizeof(ElemType));
elem->ArriveTime = occurtime;
elem->Duration = durtime;
if((occurtime+intertime) < CloseTime){ //将下一个客户的达到事件插入事件表
event_in = (Event*)malloc(sizeof(Event));
event_in->OccurTime = occurtime+intertime; //下一个客户的达到时间
event_in->NType = 0; //到达事件
// printf("下一个客户达到时间 %d\n",event_in->OccurTime);
OrderInsertEvent(ev_list,event_in);
// EventListDisplay(ev_list);
}
else{
//printf("银行要关门,下一个客户进不来\n");
}
//minQueue 为当前最短的队列的 序号
minQueue = min(NumOfQueue(&q[1]),NumOfQueue(&q[2]),NumOfQueue(&q[3]),NumOfQueue(&q[4]));
printf("进入%d号窗口\n",minQueue);
EnQueue(&q[minQueue],elem); //该客户进入一个窗口队列
// printf("客户进入窗口后 窗口情况\n");
// QueueDisplay(&q[minQueue]);
// printf("队列长度为 %d\n",NumOfQueue(&q[minQueue]));
if(NumOfQueue(&q[minQueue]) == 1){ //说明该客户入队之前,队列为空
event_out = (Event*)malloc(sizeof(Event));
event_out->OccurTime = occurtime+durtime; //该客户的离开事件
event_out->NType = minQueue; //窗口minQueue的离开事件
OrderInsertEvent(ev_list,event_out);
}
printf("\n");
// EventListDisplay(ev_list);
}
//客户离开事件
void CustomerDeparture(Event* ev){
QElemType* customer;
Event* e;
customer = DeQueue(&q[ev->NType]); //摘取队列的客户
TotalTime += ev->OccurTime-customer->ArriveTime; //该用户花费总时间
// printf("客户离开:OccurTime = %d\n",ev->OccurTime);
printf("%-4d时刻:%d号窗口 客户离开\n",ev->OccurTime,ev->NType);
printf("\n");
if(NumOfQueue(&q[ev->NType]) != 0){ //队列不是空
e = (Event*)malloc(sizeof(Event));
e->NType = ev->NType; //队列NType的离开事件
e->OccurTime = ev->OccurTime+q[ev->NType].front->next->Duration;
OrderInsertEvent(ev_list,e);
}
}
//开始模拟
void Bank_Simulation(int closetime){
Event* evt;int i;
// evt = (Event*)malloc(sizeof(Event));
CloseTime = closetime; //银行关门时间
OpenForDay(); //开门
evt = deleteHead(ev_list);
i=0;
while( evt != NULL){
// printf("取得事件 %d\n",evt->NType);
if(evt->NType == 0){
CustmerArrived(evt);
}
else{
CustomerDeparture(evt);
}
/* printf("取得头结点前\n");
printf("---------------事件表---------\n");
EventListDisplay(ev_list);
for(i=1;i<5;i++){
printf("-------------窗口%d--------\n",i);
QueueDisplay(&q[i]);
}*/
evt = deleteHead(ev_list);
}
printf("*****************************************\n");
printf(" 银行结束营业\n");
printf("业务统计结果如下:\n");
printf("接待客户总人数为:%d\n",CustomerNum);
printf("处理业务总时间为:%d\n",TotalTime);
printf("平均处理时间为: %d\n",TotalTime/CustomerNum);
}
//--------------------------主函数------------------------------------------------
void main(){
// int i;
Bank_Simulation(1200);
//--------------------下面代码作用为:测试队列与链表功能
/*
// EventListDisplay(ev_list);
// for(i=1;i<5;i++){
// printf("-------------窗口%d--------\n",i);
// QueueDisplay(&q[i]);
// }
// Event* ev1,*ev2,*ev3,*ev4;
// QElemType *qelem1,*qelem2,*qelem3;
// EventList* el;
// Queue* queue;
// ev1 = (Event*)malloc(sizeof(Event));
// ev2 = (Event*)malloc(sizeof(Event));
// ev3 = (Event*)malloc(sizeof(Event));
// el = (EventList*)malloc(sizeof(EventList));
qelem1 = (QElemType *)malloc(sizeof(QElemType));
qelem2 = (QElemType *)malloc(sizeof(QElemType));
qelem3 = (QElemType *)malloc(sizeof(QElemType));
queue = (Queue*)malloc(sizeof(Queue));
// ev1->OccurTime = 2;
// ev1->NType = 0;
// ev2->OccurTime = 1;
// ev2->NType = 1;
// ev3->OccurTime = 4;
// ev3->NType = 2;
qelem1->ArriveTime = 0;
qelem1->Duration = 1;
qelem2->ArriveTime = 1;
qelem2->Duration = 2;
qelem3->ArriveTime = 2;
qelem3->Duration = 3;
// InitEventList(el);
InitQueue(queue);
// OrderInsertEvent(el,ev1);
// EventListDisplay(el);
// printf("%d\n",el->pHead->next->OccurTime);
// printf("------------------------\n");
// OrderInsertEvent(el,ev2);
// EventListDisplay(el);
// printf("------------------------\n");
// OrderInsertEvent(el,ev3);
// EventListDisplay(el);
// printf("------------------------\n");
// ev4 = deleteHead(el);
// printf("%d\n",ev4->NType);
// deleteHead(el);
// ev4 = deleteHead(el);
// printf("%d\n",ev4->NType);
// ev4 = deleteHead(el);
// printf("%d\n",ev4->NType);
// deleteHead(el);
// deleteHead(el);
// deleteHead(el);
// EventListDisplay(el);
printf("%d ",NumOfQueue(queue));
printf("--------入队---------\n");
EnQueue(queue,qelem1);
printf("队列长度为 %d \n",NumOfQueue(queue));
QueueDisplay(queue);
printf("-------出对------------\n");
DeQueue(queue);
QueueDisplay(queue);
printf("--------入队-------------\n");
EnQueue(queue,qelem2);
printf("%d \n",NumOfQueue(queue));
QueueDisplay(queue);
printf("--------入队-----------\n");
EnQueue(queue,qelem3);
printf("%d \n",NumOfQueue(queue));
QueueDisplay(queue);
// printf("------------------------\n");
// DeQueue(queue);
// DeQueue(queue);
// DeQueue(queue);
// DeQueue(queue);
// printf("%d \n",NumOfQueue(queue));
// QueueDisplay(queue);
*/
}