#include <string>
#include <time.h>
using namespace std;
int total; //初始時銀行現存資金總額
int closeTime; //營業結束時間
int arriveTime; //兩個到達事件之間的間隔上限
int dealTime; //客戶之間交易的時間上限
int dealMoney = 30000; //交易額上限
int currentTime = 0; //當前時間
int totalTime = 0; //客戶逗留總時間
int counter = 0; //客戶總數
int number = 1; //初始客戶序列號+
struct service
{
int num; //客戶號
string type; //到達或離開
int beginTime;
int endTime;
int money; //正數為存款,負數為取款
service* next;
};
struct queue
{ //隊列
service* head;
service* rear;
};
void push(queue &q,int d)
{// 插入元素d為Q的新的隊尾元素
service* temp = new service;
temp->money = d;
temp->next = NULL;
if(NULL == q.head)
{//隊列為空,初始化
q. head = temp;
q. rear = temp;
}//if
else
{//隊列不為空,插入元素d
q. rear->next = temp;
q. rear = q.rear->next;
}//else
}
void pop(queue &q)
{// 若隊列不空,出對列函數
service* temp;
temp = q. head;
if(NULL ==q. head->next)
q.head = q. rear =NULL;
else
q. head=q. head->next;
delete temp;
}
service* front(queue &q)
{//返回隊首元素
return q. head;
}
service* back(queue &q)
{//返回隊尾元素
return q. rear;
}
service* searchAndDel(queue &q,int m)
{//在隊列中尋找可處理元素
service* sign = q. head; //標記頭節點
service* temp;
while(NULL != q. head)
{
if((-(q. head->money)) <m)
{//隊首元素可以處理
if(q. head==q.rear)
{
temp = q. head;
q. head = q. rear = NULL;
return temp;
}//if
else
{//隊首元素出列
temp = q. head;
q. head = q. head->next; // 首節點後移壹位,返回原首節點
return temp;
}//else
}//while
else
{//隊首元首不能被處理
if(q. head == q. rear){}
else
{//首節點移到隊列尾部
q. rear->next = q. head;
q. rear = q. rear->next;
q. head =q. head->next;
q. rear->next = NULL;
}//else
}//else
if(q. head == sign)//隊列循環壹周時停止
return NULL;
}
return NULL;
}
bool state =1; //用於判斷是否有窗口在處理
int currentTimeOfDeal = 0;
int theArriveTime = 0;
queue eq; //事件隊列
queue fq; //隊列壹
queue sq; //對列二
//初始化三個隊列
void arrive()
{/*"到達"函數 隨機產生顧客,進入隊列壹
產生到達事件 進入事件隊列*/
push(fq,(rand()% (2*dealMoney) -dealMoney)); //隨機產生顧客加入第壹隊列
back(fq)->beginTime = currentTime;
back(fq)->num = number;
push(eq,(back(fq)->money)); //將產生事件加入事件隊列
back(eq)->beginTime = currentTime;
back(eq)->type = "到達";
back(eq)->num = number;
++number;
}
void putMoney()
{ //存款函數
total += front(fq)->money; //更新資金總額
push(eq,front(fq)->money); //加入事件隊列 離開
back(eq)->type = "離開";
back(eq)->num = front(fq)->num;
back(eq)->endTime = (front(fq)->beginTime + rand()%dealTime +1);
++counter; //更新客戶總數
totalTime += (back(eq)->endTime - front(fq)->beginTime); //更新逗留時間
pop(fq); //刪除第壹隊列第壹個業務
currentTimeOfDeal = back(eq)->endTime;
state =0;
}
void getMoney()
{//取款函數
if( (-fq.head->money) > total )
{//資金短缺 加入第二隊列
push( sq,front(fq)->money );
back(sq)->beginTime = front(fq)->beginTime;
back(sq)->num = front(fq)->num;
pop(fq);
}//if
else
{
total += back(fq)->money;
push(eq,front(fq)->money); //加入事件隊列 離開
back(eq)->type = "離開";
back(eq)->num = front(fq)->num;
back(eq)->endTime = (front(fq)->beginTime + rand()%dealTime +1);
back(eq)->beginTime = 0;
currentTimeOfDeal = back(eq)->endTime;
++counter; //更新客戶總數
totalTime += ( back(eq)->endTime - back(fq)->beginTime ); //更新逗留時間
pop(fq); //刪除第壹隊列第壹個業務
state =0;
}//else
}
service* temped ;
int randomTemp;
void findAndDeal()
{//在對列中尋找可處理元素,對其進行處理
while( (temped= searchAndDel(sq,total))&&NULL != temped )
{//查找可處理取款
total += temped->money; //更新資金總額
push(eq,temped->money); //加入事件隊列訓 離開
back(eq)->type = "離開";
back(eq)->num = temped->num;
randomTemp = rand()%dealTime +1;
back(eq)->endTime = currentTime + randomTemp ;
currentTimeOfDeal += randomTemp;
++counter; //更新客戶總數
totalTime += ( back(eq)->endTime - temped->beginTime ); //更新逗留時間
delete temped; //刪除節點
temped = NULL;
}
state = 0;
}
int main()
{
printf(" ********************************************\n");
printf(" 歡迎進入銀行模擬系統\n");
printf(" ********************************************\n");
printf("1.開始模擬 0.退出\n");
int n;
scanf("%d",&n);
while(n==1)
{
srand(time(NULL)); //初始化隨機函數
printf("輸入銀行的初始存款:\n");
scanf("%d",&total);
printf("輸入銀行的營業時間:\n");
scanf("%d",&closeTime);
printf("輸入最大到達時間間隔:\n");
scanf("%d",&arriveTime);
printf("輸入最大的處理時間:\n");
scanf("%d",&dealTime);
theArriveTime +=rand()%arriveTime + 1; //首次到達時間
while(currentTime < closeTime)
{
++currentTime;
if( currentTimeOfDeal < currentTime ) currentTimeOfDeal = currentTime ;
if( currentTimeOfDeal == currentTime ) state = 1;
if( currentTime == theArriveTime ) //到達事件
{
arrive();
theArriveTime +=rand()%arriveTime +1;
}//if
if( 1 == state && NULL != fq.head)
{
if(fq.head->money >= 0)
{
putMoney();
findAndDeal();
}//if
else
getMoney();
}//if
}
cout <<endl<< "客戶序列"<<"\t" <<"事件類型"<<"\t\t"<<" 時間"<<"\t"<<" 處理金額"<<endl;
while( NULL != eq.head) //清除事件隊列
{
if(eq.head->type=="離開")
cout << eq.head->num<<"\t\t"<<eq.head->type<<"\t\t"<<"\t\t"<<eq.head->endTime<<"\t\t"<<eq.head->money<<endl;
if(eq.head->type=="到達")
cout << eq.head->num<<"\t\t"<<eq.head->type<<"\t\t"<<"\t\t"<<eq.head->beginTime<<"\t\t"<<eq.head->money<<endl;
pop(eq);
}
cout << "未處理客戶:" <<""<<endl;
while( NULL != fq.head)
{
totalTime += ( closeTime - fq.head->beginTime ); //更新結束時第壹隊列中未處理的客戶
cout <<fq.head->num <<" "<<endl ;
++counter;
pop(fq);
}//while
cout <<"客戶逗留平均時間為: " << totalTime/counter <<endl;
cout<<"銀行當前余額:"<<total<<endl;
break;
}//while(n==1)
return 0;
}//maim()