本文使用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();
}