银行排队系统
主要内容:
设某银行有n个窗口开展对外接待业务,从银行开门起不断有客户开展业务。客户人数众多时需要选择窗口排队,实现取票进队、排队等待、叫号服务。系统的主要功能如下:
①客户到达银行时能拿到排队号码,并能知道需要等待的人数。如果是VIP客户直接进入VIP窗口,无须加入普通客户的等待;
②可查看每个银行窗口正在给几号客户办理业务;
③客户离开银行时,有评价窗口银行职员服务的平台。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define USE_TIME 30 //客户在银行停留的最大时间
#define NEXT_TIme 5 //下一个客户到达的最大间隔时间
typedef struct E_list //有序表结点
{
int cur_time; /*记录当前时间*/
int E_type; /*记录事件类型*/
struct E_list* next; /*指针域*/
} E_List,*EvenList;
typedef struct Q_node //队列结点
{
int arrive_time; /*记录客户达到时间*/
int dur_time; /*记录客户在银行停留时间*/
struct Q_node* next; /*指针域*/
} Q_Node,*QueueNode;
typedef struct E_queue //队列操作结构
{
QueueNode front; /*指向队首元素*/
QueueNode rear; /*指向队尾元素*/
int length; /*记录队列长度*/
} E_queue,*Win_Queue;
int totalTime; /*记录总时间*/
int allcustomer; /*记录客户数量*/
int closetime; /*设置关闭时间*/
E_List ev; //有序表头节点
E_queue e_q[4]; //窗口队列操作结构
void enter_List(EvenList new_E) //进入有序表
{
EvenList agent = ev.next; //代理指针指向第一个元素
EvenList pre_E =&ev; //代理指针指向头结点
while(agent!=NULL && (new_E->cur_time > agent->cur_time)) //找到元素的插入位置
{
pre_E = agent;
agent = agent->next;
}
if(agent == NULL) /*插入到表尾*/
{
pre_E->next = new_E;
}
else /*插入到非表尾位置*/
{
new_E->next = agent;
pre_E->next = new_E;
}
agent = ev.next;
while(agent!=NULL) /*进行表的遍历*/
{
printf("(%d,%d)\n",agent->cur_time,agent->E_type);
agent = agent->next;
}
printf("\n\n");
}
void out_List(EvenList Event) //出有序表
{
/*记录待删除结点的数据后,释放该结点*/
EvenList temp = ev.next;
Event->cur_time = temp->cur_time;
Event->E_type = temp->E_type;
Event->next = NULL;
ev.next = temp->next; //出有序表节点
printf("%p\n",temp->next); //测试语句
printf("待处理客户:(%d , %d)\n",temp->cur_time,temp->E_type); /*测试语句*/
free(temp); /*释放待删除结点*/
}
void en_Queue(Win_Queue q, QueueNode new_node) //进入指定队列
{
/*将元素加入到队列末尾,并增加队列长度*/
q->rear->next = new_node;
q->rear = new_node;
q->length++;
}
void DeQueue(Win_Queue q,QueueNode node) //出队列
{
/*记录待出队列结点的数据,释放该结点后,队列长度减一*/
QueueNode temp = q->front->next;
q->front->next = temp->next;
q->length--; /*队列长度减一*/
/*存储待删除结点的数据*/
node->arrive_time = temp->arrive_time;
node->dur_time = temp->dur_time;
node->next = NULL;
}
void openforday() //初始化数据
{
int i;
EvenList temp;
QueueNode temp_q;
totalTime = 0; /*初始化时间记录器*/
allcustomer = 0; /*初始化顾客记录器*/
closetime = 5; /*初始化银行关闭时间*/
temp = (EvenList)malloc(sizeof(E_List));
if(temp == NULL)
{
printf("memory is failure!\n");
exit(1);
}
temp->cur_time = 0;
temp->E_type = 0;
temp->next = NULL;
ev.next = temp; /*将第一个客户数据(0,0,)加入到事件表*/
for(i=0; i<4; i++) //为每一个窗口队列设置头节点
{
temp_q = (QueueNode)malloc(sizeof(Q_Node));
if(temp_q == NULL)
{
printf("memory allocate is failure!\n");
exit(1);
}
temp_q->next = NULL;
e_q[i].front = temp_q;
e_q[i].rear = temp_q;
e_q[i].length = 0; /*初始化队列长度*/
}
}
void Even_head(EvenList E) //得到有序表的第一个客户
{
/*获得事件表第一个元素的副本*/
E->cur_time = ev.next->cur_time;
E->E_type = ev.next->E_type;
E->next = NULL;
}
void arrive_Event() //处理客户到达事件
{
/**
*系统产生两个随机数(x,y),x表示当前窗口type = 0的用户在银行的停留时间
*y表示下一个客户与上一个客户的间隔时间。
*如果新客户的当前时间在事件表允许的范围内,则变动事件表(记录新客户的到达事件和
*前一位客户的离开事件和队列位置)
*反之则只记录前一位客户的离开事件
*/
int i,min = 0;
QueueNode new_node; /*声明新的队列结点*/
EvenList new_E1,new_E2;/*声明新的事件结点*/
int next_time,use_time; /*随机数记录器*/
use_time = rand()%USE_TIME; /*获得当前窗口客户的银行停留时间*/
next_time = rand()%NEXT_TIme;/*获得下一位客户到达的间隔时间*/
printf("产生随机数为(%d , %d)\n",use_time,next_time); //测试语句
new_node = (QueueNode)malloc(sizeof(Q_Node)); //为队列结点分配空间
new_E1 = (EvenList)malloc(sizeof(E_List)); //为有序表结点分配空间
new_E2 = (EvenList)malloc(sizeof(E_List));
if(new_node == NULL || new_E1 == NULL || new_E2 == NULL) /*检查空间是否分配*/
{
printf("memory allocate is failure!\n");
exit(1);
}
out_List(new_E2); //取出头节点(此操作会删除原始结点)
/*初始化队列结点*/
new_node->arrive_time = new_E2->cur_time;
new_node->dur_time = use_time;
new_node->next = NULL;
/*初始化有序表结点*/
new_E1->cur_time = new_E2->cur_time+use_time; //正在窗口的用户
new_E1->next = NULL;
new_E2->cur_time = new_E2->cur_time+next_time; //新到达用户
printf("closetime = %d\n",closetime);
if((new_E2->cur_time)< closetime ) //满足事件则插入新客户
{
enter_List(new_E2); //加入一次
}
for(i=1 ; i<4; i++) /*获得最短队列*/
{
if(e_q[i].length<e_q[min].length)
{
min = i;
}
}
new_E1->E_type = min+1; /*当前客户记录自己窗口号*/
enter_List(new_E1); //重新插入前一个客户的数据
en_Queue(&e_q[min],new_node);//用户进入排队队列
for(i=0 ; i<4; i++) //测试语句(显示所有队列的长度)
{
printf("%4d\n",e_q[i].length);
}
printf("\n");
}
void leave_Event() //处理客户离开事件
{
Q_Node Qu_noe;
E_List node;
out_List(&node); /*取出事件表第一个有效结点*/
DeQueue(&e_q[node.E_type-1],&Qu_noe); /*将客户从指定队列位置取出*/
/*开始累加客户在银行的停留时间和客户数量*/
totalTime+=Qu_noe.dur_time;
allcustomer++;
//测试语句
printf("有客户从%d窗口离开,在银行停留了%d分钟!\n",node.E_type,Qu_noe.dur_time);
}
int Isempty_E() /*判断事件表是否为空*/
{
if(ev.next == NULL)
{
return 1;
}
else
{
return 0;
}
}
void Bank_simulation() //银行模拟程序
{
E_List temp;
openforday(); /*初始化数据*/
while(!Isempty_E()) /*事件表不为空则进行客户处理*/
{
Even_head(&temp); /*得到第一个节点的副本*/
if(temp.E_type == 0) /*type = 0,处理客户到达事件*/
{
arrive_Event();
}
else
{
leave_Event(); /*处理客户离开事件*/
}
}
printf("总共有%d客户,客户在银行停留总时间为:%d\n",allcustomer,totalTime);
printf("The Average time is %f\n",(double)totalTime/allcustomer);
}
int main()
{
srand(time(NULL)); //设置随机数种子
printf("银行将在6点开始营业,下午18点结束!\n");
printf("默认原数输入为(0, 0)\n"); /*第一个客户到达时间*/
Bank_simulation();
}
去猪八戒上找外包吧。
自己翘着试试“