雙端隊列隊列操作的應用 呼叫中心的離散事件模擬

1.問題

假定我們的程序模擬的是 xauat 網上書店的電話接待臺接電話(離散事件)的過程。
用戶在打電話諮詢時,先輸入自己的標識(如姓名或會員號),然後進入排隊等待被
接聽電話。xauat 服務人員會根據該用戶在書店已購買書籍的累計消費情況對撥入的
電話進行排序。累計消費超過 3000 元的爲 1 類用戶,最先得到服務;累計消費不到 
3000 元、但已滿 2000 元的 2 類用戶在沒有 1 類用戶情況下會得到服務;累計消
費不滿 2000 元、但已滿 1000 元的 3 類用戶在沒有前兩類用戶情況下會得到服務;
累積消費不滿 1000 元的用戶爲 4 類用戶,在沒有前三類用戶情況下會得到服務。同
類用戶根據時間先後確定被接聽的次序。
這些離散事件事先存入文件 sample.txt,程序接收的離散事件需要從
 sample.txt 獲取。

2.程序
sample.txt
在這裏插入圖片描述
call.cpp
頭文件dlist.cpp(見前面博客:用C++語言實現雙端隊列)

#include <iostream>
#include <string>
#include <fstream>
#include "dlist.cpp"

using namespace std;

struct message{  //撥入電話的信息
    int timestamp; //時間點
    string name; //客戶名字
    int status;  //用戶等級
    int duration; //需要持續的時間片長度
    message() //初始化
    {
        timestamp = 0;
        name = "";
        status = 0;
        duration = 0;
    }
};

void get(Dlist<message> &one,Dlist<message> &two,Dlist<message> &three,Dlist<message> &four,message *newm) //向隊列中插入信息
{
    if(1 == newm->status) //如果這個電話用戶是1類用戶
    {
        one.insertBack(newm); //在1類隊列執行尾插操作,將這個信息插入
        cout << "Call from " << newm->name << " a Level1 member" << endl; //打印出相應信息
    }
    if(2 == newm->status)//如果這個電話用戶是2類用戶
    {
        two.insertBack(newm);//在2類隊列執行尾插操作,將這個信息插入
        cout << "Call from " << newm->name << " a Level2 member" << endl; //打印出相應信息
    }
    if(3 == newm->status)//如果這個電話用戶是3類用戶
    {
        three.insertBack(newm);//在3類隊列執行尾插操作,將這個信息插入
        cout << "Call from " << newm->name << " a Level3 member" << endl;//打印出相應信息
    }
    if(4 == newm->status)//如果這個電話用戶是4類用戶
    {
        four.insertBack(newm);//在4類隊列執行尾插操作,將這個信息插入
        cout << "Call from " << newm->name << " a Level4 member" << endl;//打印出相應信息
    }
}

bool do_call(Dlist<message> &one,Dlist<message> &two,Dlist<message> &three,Dlist<message> &four,int &need_tick) //處理電話
{
    message *newm = NULL;
    newm = one.removeFront(); //嘗試從1類隊列取元素
    if(newm != NULL) //如果取到了元素,則說明1類隊列有元素,優先處理
    {
        cout << "Answering call from " << newm->name << endl;//打印出相應信息
        need_tick = newm->duration; //將這個電話所需要的持續時間片返回
        return true;
    }
    newm = two.removeFront();//嘗試從2類隊列取元素
    if(newm != NULL)//如果取到了元素,則說明2類隊列有元素,優先處理
    {
        cout << "Answering call from " << newm->name << endl;//打印出相應信息
        need_tick = newm->duration; //將這個電話所需要的持續時間片返回
        return true;
    }
    newm = three.removeFront();//嘗試從3類隊列取元素
    if(newm != NULL)//如果取到了元素,則說明3類隊列有元素,優先處理
    {
        cout << "Answering call from " << newm->name << endl;//打印出相應信息
        need_tick = newm->duration;//將這個電話所需要的持續時間片返回
        return true;
    }
    newm = four.removeFront();//嘗試從4類隊列取元素
    if(newm != NULL)//如果取到了元素,則說明4類隊列有元素,優先處理
    {
        cout << "Answering call from " << newm->name << endl;//打印出相應信息
        need_tick = newm->duration;//將這個電話所需要的持續時間片返回
        return true;
    }
    return false; //如果都沒有取到,說明所有電話都處理完了,返回false
}

int main()
{
    Dlist<message> one; //存儲撥入的1類用戶電話信息
    Dlist<message> two; //存儲撥入的2類用戶電話信息
    Dlist<message> three; //存儲撥入的3類用戶電話信息
    Dlist<message> four; //存儲撥入的4類用戶電話信息
    int tick = 0; //當前時間片
    int need_tick = 0; //完成當前電話還需要持續的時間
    int mcount = 0; //撥入電話的總數
    int i = 0;
    bool f = true; //判斷信息是否全部處理完
    message *newm;
    ifstream pin;
    pin.open("sample.txt",ios::in); //打開文件
    if (!pin.is_open())
    {
        cout << "未成功打開文件" << endl;
    }
    pin >> mcount; //讀取文件的第一行
    for(tick = 0;f;tick++) //循環,從第0個時間片開始,直到處理完所有電話退出
    {
        cout << "Starting tick #" << tick << endl; //打印出當前時間
        for(i = 0;i < mcount;i++) //循環,讀取出文件中每行的信息
        {
            newm = new message(); //分配空間存儲電話信息
            if(mcount <= 0) //如果所有信息已經讀完則跳出循環
            {
                break;
            }
            pin >> newm->timestamp >> newm->name >> newm->status >> newm->duration; //從文件中讀取一行信息
            if(newm->timestamp == tick) //判斷是否是當前時間撥入的
            {
                get(one,two,three,four,newm); //如果是當前時間撥入的電話,則調用函數將其信息存入隊列中
                mcount--; //要讀取的信息少了一行
            }
            else break;//如果不是當前時間則直接跳出循環
        }
        if(need_tick == 0) //判斷上一次通話是否還需要時間片,如果need_tick等於0,說明上一個電話已經處理完
        {
            f = do_call(one,two,three,four,need_tick); //如果上一個電話已經處理完則開始處理下一個電話
        }
        need_tick--;//減去當前消耗的時間片
    }
    delete newm;
}

3.結果
在這裏插入圖片描述
結果解釋:

 這個程序是雙端隊列中隊列的應用,處理的是模擬的離散事件。程序運行結果如圖所
 示,按照要求每個時間片開始時先打印“Starting tick #<tick>”提示信息,然後
 先打印出當前時間片接收到的電話,將其存儲起來,然後打印當前時間片中處理的電
 話,直到所有電話處理完程序結束。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章