文章目录

  • 前言
  • 一、题目要求
  • 二、解决思路
    • 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-0xffff即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 队列模拟 学习笔记相关推荐

  1. 用蒙特卡洛法实现对排队等待问题的计算机模拟

    在日常生活中,我们每天都会遇到各种各样的排队.比如:银行中取款要排队,火车站买票要排队,超市.商场中购物付款要排队,预订旅馆或机票时也要排队,人们仿佛置身于一个排队的社会. 所谓排队,就是等候消费服务 ...

  2. LeetCode 860[Python]. 柠檬水找零 在柠檬水摊上,每一杯柠檬水的售价为 5 美元。 顾客排队购买你的产品,(按账单 bills 支付的顺序)一次购买一杯。

    LeetCode 860. 柠檬水找零 在柠檬水摊上,每一杯柠檬水的售价为 5 美元. 顾客排队购买你的产品,(按账单 bills 支付的顺序)一次购买一杯. 每位顾客只买一杯柠檬水,然后向你付 5 ...

  3. 显示12306服务器处理中正在排队,12306排队等待中怎么办 12306一直在排队解决方法(图文)...

    12306一直在排队解决方法: 大家都知道,使用12306订票是为了图个方便,不用去火车站排队买票了,但是现在使用12306的用户竟然遇到了12306购票还要排队的情况,这到底是怎么回事呢? 如果您也 ...

  4. 显示12306服务器处理中正在排队,12306排队等待中怎么回事_12306排队等待时间_12306一直在排队解决方法...

    12306排队等待中怎么办?用网上订票时,有时会显示"12306排队等待中",下文介绍12306一直在排队解决方法,一起和小编来了解下吧! 12306一直在排队解决方法: 大家都知 ...

  5. javascript 等待指定时间_javascript的单线程和任务队列

    一.JavaScript为什么设计为单线程? JavaScript语言的一大特点就是单线程,换言之就是同一个时间只能做一件事.其他任务都必须在后面排队等待. for(var i = 0; i < ...

  6. Windows事件等待学习笔记(四)—— 事件信号量互斥体

    Windows事件等待学习笔记(四)-- 事件&信号量&互斥体 要点回顾 事件 实验:验证SignalState 第一步:编译并运行以下代码 第二步:观察结果 第三步:修改代码并执行 ...

  7. Windows事件等待学习笔记(三)—— WaitForSingleObject函数分析

    Windows事件等待学习笔记(三)-- WaitForSingleObject函数分析 要点回顾 WaitForSingleObject NtWaitForSingleObject KeWaitFo ...

  8. Windows事件等待学习笔记(二)—— 线程等待与唤醒

    Windows事件等待学习笔记(二)-- 线程等待与唤醒 要点回顾 等待与唤醒机制 可等待对象 可等待对象的差异 线程与等待对象 一个线程等待一个对象 实验 第一步:编译并运行以下代码 第二步:在Wi ...

  9. Windows事件等待学习笔记(一)—— 临界区自旋锁

    Windows事件等待学习笔记(一)-- 临界区&自旋锁 基础知识 演示代码 案例一 案例二 LOCK 单行代码原子操作 多行代码原子操作 临界区 演示代码 手动实现 自旋锁 分析 KeAcq ...

最新文章

  1. 让机器听懂人话的自然语言处理技术究竟神奇在哪里?
  2. Git config 查看和设置配置信息
  3. 读书笔记:怪侠一枝梅 看后感
  4. 通过Zookeeper动态感知服务器上下线[案例]
  5. 零基础如何学习Java,这里分享一些技巧心得
  6. Linux下Anaconda3安装及使用教程
  7. ui设计颜色的使用_UI设计中颜色使用的10条原则
  8. 基础算法 —— 模拟思维
  9. 【TensorFlow】TensorFlow函数精讲之tf.train.exponential_decay()
  10. sed查找文件包含字段_sed(查找替换) 与awk(提取字段)
  11. 你知道这些使用Linux虚拟桌面的益处吗?
  12. Python糗百爬虫(精简版)
  13. 动软DBUtility类库DbHelperSQLP实现多数据库连接
  14. 夜深人静写算法(二)- 动态规划
  15. FTP 通过cmd命令上传下载文件
  16. ERP100人物.第25期【风里来云里去兮,风行天下志更坚】 风云子
  17. 别人眼中的程序猿和现实中的程序猿差别在哪?
  18. ie8 css hack 只适用ie8的css写法
  19. 为什么我会性格懦弱?如何改变懦弱的性格?
  20. 使用免费绿色工具chfs,将文件夹共享成网盘

热门文章

  1. 2023年第五届人工智能与机器学习国际会议(FAIML 2023)
  2. 洛克王国服务器维护,洛克王国3月6日服务器公告 剧情更新百年大潮
  3. top 1000 site page rank
  4. STM32 HAL RTC配置及优化
  5. Pytorch+PyG实现EdgeCNN
  6. 流水车间调度问题混合整数规划模型
  7. JSON编辑器,在线与离线
  8. 实现10进制转换为2进制
  9. MAC M1芯片安装python3.6环境
  10. OSChina 周一乱弹 —— 好气哦,还是要保持微笑