【C++】Heather银行对顾客排队等待的时间进行估测问题 《C++ Primer Plus》12.7 队列模拟 学习笔记
文章目录
- 前言
- 一、题目要求
- 二、解决思路
- 1.Queue类
- 具体的公有接口声明如下:
- 私有实现:
- 析构函数
- 2.Customer类
- 公有接口
- 实现如下
- 3.ATM模拟
- 4.完整代码
- queue.h
- queue.cpp
- bank.cpp
- 5.结果展示
- 总结
前言
今天在看C++ Primer Plus的书的第12章,有一个队列模拟题,遂跟着书一起把代码敲了一遍,并记录如下。以供大家参考和我自己复习!
一、题目要求
Heather银行打算在Food Heap超市开设一个自动柜员机(ATM)。Food Heap超市的管理者担心排队等待使用ATM的人流会干扰超市的交通,希望限制排队等待的人数。Heather银行希望对顾客排队等待的时间进行估测。要编写一个程序来模拟这种情况,让超市的管理者可以了解 ATM可能造成的影响。
队列中的项目是顾客.Heather银行的代表介绍:通常,三分之一的顾客只需要一分钟便可获得服务,三分之一的顾客需要两分钟,另外三分之一的顾客需要三分钟.另外,顾客到达的时间是随机的,但每个小时使用自动柜员机的顾客数量相当稳定.工程的另外两项任务是:设计一个表示顾客的类;编写一个程序来模拟顾客和队列之间的交互
二、解决思路
1.Queue类
对于Queue类,经过分析,我们采用链表来满足对列要求,因为队列是先进先出的FIFO,所以我们使用了Node结点struct Node {Item& item; struct Node *next};
这样在对列进出时非常方便,不熟悉的同学可以去看一下链表。
具体的公有接口声明如下:
class Queue
{public://接口Queue(int qs = Q_SIZE); //默认队列可储存10个项目~Queue();bool isempyt() const;bool isfull() const;int queuecount() const;bool enqueue(const Item &item); //addbool dequeue(Item& item);//removeprivate:enum { Q_SIZE = 10 };struct Node{Item item;struct Node* next; //指向下一个结点};Node* front;Node* rear;int items;const int qsize;//复制构造函数Queue(const Queue& q) : qsize(0) { }//运算符重载Queue& operator=(const Queue& q) { return *this; }
};
注:bool isempyt() const; bool isfull() const; int queuecount() const;
加const是为了保护数据,只读不改变数据。
其中我们把复制构造函数和运算符重载放在了private
中有两个作用:1.它避免了本来自动默认生成的方法定义2.因为这些方法是私有的,所以不能被广泛使用。(其实这里小唐也不太理解,但是书上是这样说的,并且我放在public
中好像确实有点吧小问题,有知道的兄弟们可以教教我!)。反正就是为了避免程序崩溃。
私有实现:
Queue::Queue(int qs) : qsize(qs) {front = rear = nullptr;items = 0;
}Queue::~Queue() {Node* temp;while (front != nullptr) {temp = front;front= front -> next;delete temp;}
}bool Queue::isempyt() const {return 0 == items;
}bool Queue::isfull() const {return qsize == items;
}bool Queue::enqueue(const Item& item) {if (isfull()) {return false;}Node* add = new Node;add->item = item;add->next = nullptr;items++;if (front == nullptr) {front = add;}else{rear->next = add;}rear = add;return true;
}bool Queue::dequeue(Item& item) {if (front == nullptr) {return false;}item = front->item;items--;Node* temp = front;front = front->next;delete temp;if (0 == items) {rear = nullptr;}return true;
}int Queue::queuecount() const {return items;
}
代码大多比较好理解,我就只解释一下我写的时候一开始有点迷糊的地方叭,顺便给自己再复习一遍!
析构函数
Queue::~Queue() {Node* temp;while (front != nullptr) {temp = front;front= front -> next;delete temp;}
}
虽然在类构造函数中我们没有使用new
,但是我们向队列中添加对象会调用new
来创建新的节点,所以我们需要一个显式析构函数,它从表头开始删除节点,也就是我们先前提到的先进先出FIFO。
2.Customer类
公有接口
class Customer
{public:Customer() { arrive = processtime = 0; }void set(long when);long when() const { return arrive; }int ptime() const { return processtime; }private:long arrive; //到达时间int processtime;
};
Customer中有两个私有成员 顾客到达时间 和 顾客处理时间,默认构造函数将创建一个空客户,set()成员函数为arrive和processtime设置参数,processtime根据题目将被设置成一个1-3分钟的随机值。
实现如下
void Customer::set(long when) {processtime = std::rand() % (3-1+1) + 1; //处理时间设置为1-3中的任意一个arrive = when;
}
这里介绍一下随机数是怎么产生的:std::rand() % (b-a+1)+a
表示产生一个a-b之间的随机整数
3.ATM模拟
是否来了一个新的客户
bool newcustomer(double x) {return (std::rand() * x / RAND_MAX < 1); //产生一个[0,x]的随机数
}
rand()
会产生一个0-0xfff
f即0-32767
之间的随机数,RAND_MAX=0X7fffff=32767
,故rand()/RAND_MAX
会产生一个[0,1]区间的随机数
害好像代码有点好理解的我还有很多注释,就不解释了,直接放代码叭,如果大家有问题就评论留言就好!
4.完整代码
queue.h
#ifndef QUEUE_H_
#define QUEUE_H_class Customer
{public:Customer() { arrive = processtime = 0; }void set(long when);long when() const { return arrive; }int ptime() const { return processtime; }private:long arrive; //到达时间int processtime;
};typedef Customer Item;class Queue
{public://接口Queue(int qs = Q_SIZE); //默认队列可储存10个项目~Queue();bool isempyt() const;bool isfull() const;int queuecount() const;bool enqueue(const Item &item); //addbool dequeue(Item& item);//removeprivate:enum { Q_SIZE = 10 };struct Node{Item item;struct Node* next; //指向下一个结点};Node* front;Node* rear;int items;const int qsize;//复制构造函数Queue(const Queue& q) : qsize(0) { }//运算符重载Queue& operator=(const Queue& q) { return *this; }
};#endif // !QUEUE_H_
queue.cpp
#include "queue.h"
#include <cstdlib>void Customer::set(long when) {processtime = std::rand() % (3-1+1) + 1; //处理时间设置为1-3中的任意一个arrive = when;
}Queue::Queue(int qs) : qsize(qs) {front = rear = nullptr;items = 0;
}Queue::~Queue() {Node* temp;while (front != nullptr) {temp = front;front= front -> next;delete temp;}
}bool Queue::isempyt() const {return 0 == items;
}bool Queue::isfull() const {return qsize == items;
}bool Queue::enqueue(const Item& item) {if (isfull()) {return false;}Node* add = new Node;add->item = item;add->next = nullptr;items++;if (front == nullptr) {front = add;}else{rear->next = add;}rear = add;return true;
}bool Queue::dequeue(Item& item) {if (front == nullptr) {return false;}item = front->item;items--;Node* temp = front;front = front->next;delete temp;if (0 == items) {rear = nullptr;}return true;
}int Queue::queuecount() const {return items;
}
bank.cpp
/* 小唐 2023/1/1模拟ATM程序: 用户需输入1.限制排队等待的最大人数2.程序模拟的持续时间(小时)3.平均每小时客户数
*/#include <iostream>
#include <cstdlib>
#include <ctime>
#include "queue.h"const int MIN_PER_HR = 60;// 60min/hourbool newcustomer(double x); //是否接收新客户int main() {using std::cin;using std::cout;using std::endl;using std::ios_base;std::srand((unsigned int)std::time(0)); //种下一个随机种子cout << "Bank of Heather Automatic Teller\n";cout << "--------------------------------\n";cout << "输入限制的排队等待的最大人数: ";int qs;cin >> qs;Queue line(qs);cout << "输入模拟运行时间: ";int hours;cin >> hours;long cyclelimit = hours * MIN_PER_HR; cout << "输入平均每小时客户数: ";double perhour;cin >> perhour;double min_per_cust;min_per_cust = MIN_PER_HR / perhour;Item temp; long turnaway = 0;long customers = 0;long served = 0;long sum_line = 0;long wait_time = 0;long line_wait = 0;for (int cycle = 0; cycle < cyclelimit; cycle++) {if (newcustomer(min_per_cust)){if (line.isfull()) //队满了拜拜了您turnaway++;else {customers++;temp.set(cycle); //随机设置一个处理时间[1,3]minline.enqueue(temp); //排队去叭您}}if ((wait_time <= 0) && (!line.isempyt())) { line.dequeue(temp); //处理完了可以滚蛋了wait_time = temp.ptime();line_wait += cycle - temp.when();served++;}if (wait_time > 0)wait_time--;sum_line += line.queuecount();}if (customers > 0) {cout << "接收的客户数: " << customers << endl;cout << "服务的客户数: " << served << endl;cout << "人满潇洒转身离开的客户数: " << turnaway << endl;cout << "队伍平均数:";cout.precision(2);cout.setf(ios_base::fixed, ios_base::floatfield);cout << (double)sum_line / cyclelimit << endl;cout << "平均等待时间: " << (double)line_wait / served << "分钟" << endl;}elsecout << "没人来!服了!" << endl;return 0;
}bool newcustomer(double x) {return (std::rand() * x / RAND_MAX < 1); //产生一个[0,x]的随机数
}
5.结果展示
总结
最后完结撒花~虽然这个程序比较简单,但是我在敲的时候还是遇到了不少细节问题,唐怡佳继续努力叭!
我也会把完整工程文件上传资源,有需要的小伙伴可以自取哦!
【C++】Heather银行对顾客排队等待的时间进行估测问题 《C++ Primer Plus》12.7 队列模拟 学习笔记相关推荐
- 用蒙特卡洛法实现对排队等待问题的计算机模拟
在日常生活中,我们每天都会遇到各种各样的排队.比如:银行中取款要排队,火车站买票要排队,超市.商场中购物付款要排队,预订旅馆或机票时也要排队,人们仿佛置身于一个排队的社会. 所谓排队,就是等候消费服务 ...
- LeetCode 860[Python]. 柠檬水找零 在柠檬水摊上,每一杯柠檬水的售价为 5 美元。 顾客排队购买你的产品,(按账单 bills 支付的顺序)一次购买一杯。
LeetCode 860. 柠檬水找零 在柠檬水摊上,每一杯柠檬水的售价为 5 美元. 顾客排队购买你的产品,(按账单 bills 支付的顺序)一次购买一杯. 每位顾客只买一杯柠檬水,然后向你付 5 ...
- 显示12306服务器处理中正在排队,12306排队等待中怎么办 12306一直在排队解决方法(图文)...
12306一直在排队解决方法: 大家都知道,使用12306订票是为了图个方便,不用去火车站排队买票了,但是现在使用12306的用户竟然遇到了12306购票还要排队的情况,这到底是怎么回事呢? 如果您也 ...
- 显示12306服务器处理中正在排队,12306排队等待中怎么回事_12306排队等待时间_12306一直在排队解决方法...
12306排队等待中怎么办?用网上订票时,有时会显示"12306排队等待中",下文介绍12306一直在排队解决方法,一起和小编来了解下吧! 12306一直在排队解决方法: 大家都知 ...
- javascript 等待指定时间_javascript的单线程和任务队列
一.JavaScript为什么设计为单线程? JavaScript语言的一大特点就是单线程,换言之就是同一个时间只能做一件事.其他任务都必须在后面排队等待. for(var i = 0; i < ...
- Windows事件等待学习笔记(四)—— 事件信号量互斥体
Windows事件等待学习笔记(四)-- 事件&信号量&互斥体 要点回顾 事件 实验:验证SignalState 第一步:编译并运行以下代码 第二步:观察结果 第三步:修改代码并执行 ...
- Windows事件等待学习笔记(三)—— WaitForSingleObject函数分析
Windows事件等待学习笔记(三)-- WaitForSingleObject函数分析 要点回顾 WaitForSingleObject NtWaitForSingleObject KeWaitFo ...
- Windows事件等待学习笔记(二)—— 线程等待与唤醒
Windows事件等待学习笔记(二)-- 线程等待与唤醒 要点回顾 等待与唤醒机制 可等待对象 可等待对象的差异 线程与等待对象 一个线程等待一个对象 实验 第一步:编译并运行以下代码 第二步:在Wi ...
- Windows事件等待学习笔记(一)—— 临界区自旋锁
Windows事件等待学习笔记(一)-- 临界区&自旋锁 基础知识 演示代码 案例一 案例二 LOCK 单行代码原子操作 多行代码原子操作 临界区 演示代码 手动实现 自旋锁 分析 KeAcq ...
最新文章
- 让机器听懂人话的自然语言处理技术究竟神奇在哪里?
- Git config 查看和设置配置信息
- 读书笔记:怪侠一枝梅 看后感
- 通过Zookeeper动态感知服务器上下线[案例]
- 零基础如何学习Java,这里分享一些技巧心得
- Linux下Anaconda3安装及使用教程
- ui设计颜色的使用_UI设计中颜色使用的10条原则
- 基础算法 —— 模拟思维
- 【TensorFlow】TensorFlow函数精讲之tf.train.exponential_decay()
- sed查找文件包含字段_sed(查找替换) 与awk(提取字段)
- 你知道这些使用Linux虚拟桌面的益处吗?
- Python糗百爬虫(精简版)
- 动软DBUtility类库DbHelperSQLP实现多数据库连接
- 夜深人静写算法(二)- 动态规划
- FTP 通过cmd命令上传下载文件
- ERP100人物.第25期【风里来云里去兮,风行天下志更坚】 风云子
- 别人眼中的程序猿和现实中的程序猿差别在哪?
- ie8 css hack 只适用ie8的css写法
- 为什么我会性格懦弱?如何改变懦弱的性格?
- 使用免费绿色工具chfs,将文件夹共享成网盘