3.5离散事件模拟
這節(jié)是銀行業(yè)務(wù)模擬程序、
假設(shè)某銀行有4個(gè)窗口對外接待客戶,每個(gè)窗口接待一個(gè)人,當(dāng)有人要辦理業(yè)務(wù)的時(shí)候,如果某窗口空閑,則可辦理,如果不空閑,則排在人最少的后面。現(xiàn)編制一個(gè)程序以模擬銀行這種活動并計(jì)算一天中客戶在銀行逗留的平均時(shí)間。
為了計(jì)算這個(gè)平均時(shí)間,要掌握每個(gè)客戶到達(dá)銀行和離開銀行這兩個(gè)時(shí)刻,后者減去前者就是逗留時(shí)間。所有客戶逗留時(shí)間的總和被一天內(nèi)進(jìn)入銀行的客戶數(shù)除便是所求的平均時(shí)間。
下面是銀行業(yè)務(wù)模擬,統(tǒng)計(jì)一天內(nèi)客戶在銀行逗留的平均時(shí)間:
代碼如下:
void Bank_Simulation(int CloseTime) {OpenForDay(); //初始化while (MoreEvent){EventDrived(OccurTime, EventType); //事件驅(qū)動switch (EventType){case 'A':CustomerArrived(); break;case 'D':CustomerDeparture();break;default:Invalid();}}CloseForDay(); }下面分析下:
1.這個(gè)OpenForDay可以理解成開啟一個(gè)計(jì)時(shí)器,然后最后有CloseForDay()就是關(guān)閉計(jì)時(shí)器。
2.EventDrived(OccurTime,EventType)這個(gè)我們可以看見有個(gè)事件驅(qū)動,第一個(gè)參數(shù)是當(dāng)前時(shí)間,第二個(gè)參數(shù)是事件類型。
3.這個(gè)事件類型有A,D,和其他,A代表Arrived,D代表Departure,其他事件缺省情況(默認(rèn)情況)是無效的。
算法3.6:
模擬程序中有4個(gè)窗口業(yè)務(wù)窗口,所以要4個(gè)隊(duì)列,對每個(gè)隊(duì)頭客戶都存在一個(gè)將要驅(qū)動的客戶離開事件。
因此在任何時(shí)刻即將發(fā)送的事件只有5種可能:
1.新的客戶到達(dá)。
2.1號窗口客戶離開。
3.2號窗口客戶離開。
4.3號窗口客戶離開。
5.4號窗口客戶離開。
下面是有序鏈表和隊(duì)列的結(jié)構(gòu)體:
typedef struct{int OccurTime; //事件發(fā)生時(shí)刻int NType; //事件類型,0表示到達(dá)事件,1-4表示4個(gè)窗口的離開事件 }Event,ElemType;typedef LinkList EventList; //事件鏈表類型,定義為有序鏈表typedef struct{int ArrivalTime; //到達(dá)時(shí)刻int Duration; //辦理業(yè)務(wù)的時(shí)間 }QElemType;由于在實(shí)際的銀行中,客戶到達(dá)的時(shí)刻以及辦理事物所需時(shí)間都是隨機(jī)的,在模擬程序中可用隨機(jī)數(shù)來代替。假設(shè)第一個(gè)顧客進(jìn)門的時(shí)刻為0,即是模擬程序處理的第一個(gè)事件,之后每個(gè)客戶到達(dá)的時(shí)刻在前一個(gè)客戶到達(dá)時(shí)設(shè)定。因此在客戶達(dá)到事件發(fā)生時(shí)需先產(chǎn)生倆個(gè)隨機(jī)數(shù):其一為此時(shí)刻到達(dá)的客戶辦理事物所需時(shí)間durtime;其二為下一客戶到達(dá)時(shí)間間隔imtertime,假設(shè)事件發(fā)生的時(shí)刻為Occurtime,則下一個(gè)客戶到達(dá)的時(shí)刻為Occurtime+intertime。由此應(yīng)產(chǎn)生一個(gè)新的客戶到達(dá)事件插入事件表;剛到達(dá)的客戶則應(yīng)插入到當(dāng)前所含元素最少的隊(duì)列中;若插入前為空,則產(chǎn)生一個(gè)客戶立刻事件插入事件表。
客戶離開事件的處理比較簡單。首先計(jì)算該客戶在銀行逗留的時(shí)間,然后從隊(duì)列中刪除該客戶后查看隊(duì)列是否空,若空則設(shè)定一個(gè)新的隊(duì)頭客戶離開事件。
算法如下所示:
// 程序中用到的主要變量 EventList ev; // 事件表 Event en; // 事件 LinkQueue q[5]; // 4個(gè)客戶隊(duì)列,q[0]未用 QElemType customer; // 客戶記錄 int TotalTime, CustomerNum; // 累計(jì)客戶逗留時(shí)間, 客戶數(shù) int CloseTime;//---------------- 算法 3.7 ------------------int cmp(Event a, Event b) {// 依事件a的發(fā)生時(shí)刻< 或= 或> 事件b的發(fā)生時(shí)刻分別返回-1或0或1if (a.OccurTime < b.OccurTime) return -1;if (a.OccurTime > b.OccurTime) return +1;return 0; }void Random(int &durtime, int &intertime) { // 生成隨機(jī)數(shù)durtime = random(2, 10);intertime = random(10); }int Minimum(LinkQueue q[]) { // 求長度最短隊(duì)列int minlen = QueueLength(q[1]);int i = 1;for (int j=2; j<=4; j++)if (QueueLength(q[j]) < minlen) {minlen = QueueLength(q[j]);i = j;}return i; }void OpenForDay() {// 初始化操作TotalTime = 0; CustomerNum = 0; // 初始化累計(jì)時(shí)間和客戶數(shù)為0InitList(ev); // 初始化事件鏈表為空表en.OccurTime = 0; en.NType = 0; // 設(shè)定第一個(gè)客戶到達(dá)事件OrderInsert(ev, en, cmp); // 按事件發(fā)生時(shí)刻的次序插入事件表for (int i=1; i<=4; ++i) InitQueue(q[i]); // 置空隊(duì)列 } // OpenForDayvoid CustomerArrived() {// 處理客戶到達(dá)事件,en.NType=0int durtime, intertime, i, t;++CustomerNum;printf("Customer %d arrived at %d and ", CustomerNum, en.OccurTime);Random(durtime, intertime); // 生成隨機(jī)數(shù)t = en.OccurTime + intertime; // 下一客戶到達(dá)時(shí)刻if (t<CloseTime) // 銀行尚未關(guān)門,插入事件表OrderInsert(ev, MakeElem(t, 0), cmp);i = Minimum(q); // 求長度最短隊(duì)列printf("enter the Queue %d\n", i);EnQueue(q[i], MakeQElem(en.OccurTime, durtime));if (QueueLength(q[i]) == 1) //設(shè)定第i隊(duì)列的一個(gè)離開事件并插入事件表OrderInsert(ev, MakeElem(en.OccurTime+durtime, i), cmp); } // CustomerArrivedvoid CustomerDeparture() {// 處理客戶離開事件,en.NType>0printf("Customer departure at %d\n", en.OccurTime);int i = en.NType; DeQueue(q[i], customer); //刪除第i隊(duì)列的排頭客戶TotalTime += en.OccurTime-customer.ArrivalTime; // 累計(jì)客戶逗留時(shí)間if (!QueueEmpty(q[i])) { // 設(shè)定第i隊(duì)列的一個(gè)離開事件并插入事件表GetHead (q[i], customer);OrderInsert(ev, MakeElem(en.OccurTime+customer.Duration, i), cmp);} } // CustomerDeparturevoid Bank_Simulation(int closetime) {int i = 0;BLink p;CloseTime = closetime;printf("Bank_Simulation( %d ) ----- 銀行業(yè)務(wù)模擬\n", closetime);OpenForDay(); // 初始化while (!ListEmpty(ev)) {printList(ev);if (DelFirst(GetHead(ev), p)) {en = GetCurElem(p);if (en.NType == 0)CustomerArrived(); // 處理客戶到達(dá)事件else CustomerDeparture(); // 處理客戶離開事件}if (++i % 9 == 0) {printf("\n----- 按任意鍵,繼續(xù) -----");getch();printf("\n\n");}}// 計(jì)算并輸出平均逗留時(shí)間printf("\nThe Average Time is %f\n", (float)TotalTime/CustomerNum); } // Bank_Simulation總結(jié)
- 上一篇: ibm z系列服务器 cpu,全球最快C
- 下一篇: 2.2线性表的顺序表示和实现