四、C++實現佇列(queue)資料結構
阿新 • • 發佈:2018-12-08
本文使用C++實現佇列資料結構,與棧一樣,佇列(queue)也是線性邏輯的資料結構,佇列結構同樣支援物件的插入和刪除,但是兩種操作的物件範圍分別被限制於隊尾和隊頭,並且這兩種操作又分別被稱為入隊和出隊。
佇列結構的特點:先進先出(First in first out,FIFO)
一、佇列資料結構的實現
佇列資料結構的實現可通過對vector或則list類封裝得到,但是考慮到佇列內元素的移動,採用list結構更加高效,所以這裡使用C++的繼承機制,直接從list類繼承,並對部分函式進行再封裝重新命名,得到queue類。(list.h的實現見之前的部落格)
操作 | 功能 | 物件 |
queue() | 預設建構函式 | |
~queue() | 預設解構函式 | |
size() | 返回佇列內部成員數量 | 佇列 |
empty() | 判斷佇列是否為空 | 佇列 |
enqueue(const T& e) | 指定元素入隊 | 佇列 |
dequeue() | 出隊 | 佇列 |
front() | 反對隊頭的引用 | 佇列 |
display() | 列印佇列內部結構 | 佇列 |
#pragma once #include"list.h" template<typename T> class queue :public list<T> { public: //建構函式 queue(){} ~queue(){} //解構函式 int size() { return list<T>::size(); } bool empty() { if (size()) return false; else return true; } void enqueue(const T& e) { insertAsLast(e); } T dequeue() { return remove(first()); } T& front() { return first()->data; } void display() { list<T>::display; } };
二、佇列資料結構的應用
和日常生活中的許多排隊例子一樣,佇列結構憑藉著先進先出(FIFO)這一特點,很適合實現公平和高效的資源分配規則。例如windows作業系統的訊息機制就是基於佇列結構,而且我還知道有其他一些大型伺服器框架就是基於佇列的。
這裡利用佇列結構實現銀行視窗服務的模擬。設銀行有nWin個視窗,顧客按照隨機概率到達,且每個客戶需要隨機的服務時間,然後這些客戶選擇佇列最短的視窗進行排隊,每個客戶需要的服務時間結束後出隊。
#include<iostream>
#include"queue.h"
using namespace std;
struct client
{
int window; //所屬視窗
int time; //所需服務時間
};
int bestWindow(queue<client>* w, int n) //搜尋出佇列長度最短的視窗號
{
int minTime = w[0].size();
int minWin = 0;
for (int i = 1; i < n; i++)
{
if (minTime > w[i].size())
{
minTime = w[i].size();
minWin = i;
}
}
return minWin;
}
void simulation(int nWin, int servTime) //視窗總數,總服務時間
{
queue<client>* windows = new queue<client>[nWin]; //建立視窗
for (int t = 0; t < servTime; t++) //在服務時間內
{
cout << "-------第" << t + 1 << "個服務時間單元-------" << endl;
//模擬銀行來新客人
if (rand() % ( nWin+ 1)) //客人以rand()/(rand() + 1)的概率到達
{
client c;
c.time = 1 + rand() % 10;
c.window = bestWindow(windows, nWin);
windows[c.window].enqueue(c);//客戶入隊
cout << "-new client ! (" << c.time << "," << c.window << ")" << endl;
}
//模擬視窗服務客人
for (int i = 0; i < nWin; i++)
{
cout << "-第" << i << "個視窗還剩" << windows[i].size() << "個客人" << endl;
if (!windows[i].empty()) //若當前視窗前有佇列
{
windows[i].front().time--;
if (windows[i].front().time == 0) //此客戶服務結束
{
windows[i].dequeue();
}
}
}
}
delete[] windows; //有new就有delete
}
void main(int argc, char *argv[])
{
//模擬銀行視窗服務
simulation(4, 10000);
getchar();
}