数据结构大作业W1

银行叫号系统

系统要求:

  1. 五个服务窗口;
  2. 一个客户队列,按先后顺序排列;
  3. 显示每个窗口顺序号、等待人数、每个顾客得到服务等待时间与最后平均时间及总客户数;

数据结构设计

  • 服务窗口 Windows
class Windows {
private:
	windows_status status;
	list<Customer> Customer_list;

public:
	Windows();
	void set_busy();
	void set_avail();
	void redin_customer(Customer &x);
	bool is_avail();
	int get_people_num();
	double get_average_time();
};
  • 客户结构体 Customer
class Customer {
public:
	Customer(int num, int arr,int dur= get_random(RP));
	int get_num();
	int get_arrive_time();
	int get_duration();
	int get_wait_time();
	void set_wait_time(int time);
private:
	int num;
	int arrive_time;//到达时间
	int duration;//随机生成的离开时间
	int wait_time;//计算得到等待时间
};
  • 系统总控 System
class System {
private:
	double AverageWaitTime;
	Windows wins[5];
	list<Event> event_list;
	list<Customer> customer_list;
	int current_time;
	long int total_time;
	Event* current_event;

	void customerArrived();//顾客到达
	void customerDone();//顾客离开
	int get_avail_windows();//检索可利用窗口
	
public:
	System(long int totaltime=10000) {
		AverageWaitTime = 0;
		Event begin(0);//第一个顾客到达
		event_list.push_back(begin);
		current_time = 0;
		total_time = totaltime;
		current_event = &(*event_list.begin());
	}

	double get_AverageWaitTime() {
		return AverageWaitTime;
	}
	
	int get_current_time() {
		return current_time;
	}
	void run();//运行
	friend void insert_by_time(System& system, Event& event);
};
  • 随机数获取 get_random();
double U_Random();
int get_random(int Lambda)
{
	int  k = 0;
	long double p = 1.0;
	long double l = exp(-Lambda);
	srand((unsigned)time(NULL));
	//printf("%1.5Lf\n", l);
	while (p >= l)
	{
		double u = U_Random();
		p *= u;
		k++;
	}
	return k - 1;
}

double U_Random()
{
	double f;
	f = (float)(rand() % 100);
	return f / 100;
}

困难与解决方法:

  • 如何驱动

    使用任务队列,将任务分为 a,顾客到达 b,顾客离开

    在a任务中遍新顾客入队并进行判断,第一层判断其到达时间是否超过最大服务时间,没有则生成此顾客信息,进行第二层判断,是否有空闲窗口,若有空闲窗口,则进入窗口操作,若无,则进入顾客等待队列,待b任务发生时检索顾客等待队列以进入下一步操作。

    在b任务中,顾客离开后对顾客等待队列进行检索,若有等待顾客则使队列首位(最先抵达)者进入窗口操作,若无,则置此窗口为空闲,等待顾客到达。

  • 如何停止

    规定给出一个服务末尾时间,入队操作发生时间晚于次时间则停止生成新顾客。

  • 如何生成随机顾客队列

    通过控制顾客到达时间间隔为随机达到实现随机顾客队列的目的。

编译调试环境:

  • Visual Studio 2017
#ifndef Customer_hpp
#define Customer_hpp
#define RP 100//随机数参数,最大值
#include <cmath>
#include <cstdlib>
#include "random.hpp"

class Customer {
public:
	Customer(int num, int arr,int dur= get_random(RP)) :
		num(num),
		wait_time(0),
		arrive_time(arr),
		duration(dur){}

	int get_num() {
		return num;
	}
	int get_arrive_time() {
		return arrive_time;
	}
	int get_duration() {
		return duration;
	}
	int get_wait_time() {
		return wait_time;
	}
	void set_wait_time(int time) {
		wait_time = time;
		return;
	}
private:
	int num;
	int arrive_time;//到达时间
	int duration;//随机生成的离开时间
	int wait_time;//计算得到等待时间
};
#endif

#ifndef random_hpp
#define random_hpp

#include <cstdlib>
#include <cmath>
#include <ctime>
//double get_random(double max = 1) {
//	return ((double)std::rand() / (RAND_MAX))*max;
//}
double U_Random();
int get_random(int Lambda)
{
	int  k = 0;
	long double p = 1.0;
	long double l = exp(-Lambda);
	srand((unsigned)time(NULL));
	//printf("%1.5Lf\n", l);
	while (p >= l)
	{
		double u = U_Random();
		p *= u;
		k++;
	}
	return k - 1;
}

double U_Random()
{
	double f;
	f = (float)(rand() % 100);
	return f / 100;
}

#endif // !random_hpp



#ifndef Windows_hpp
#define Windows_hpp
#include <list>
#include "Customer.hpp"
using namespace std;

enum windows_status {
	avail,
	unavail
};

class Windows {
private:
	windows_status status;
	list<Customer> Customer_list;

public:
	Windows():
		status(avail){}
	void set_busy() {
		status = unavail;
	}
	void set_avail() {
		status = avail;
	}
	void redin_customer(Customer &x) {
		Customer_list.push_back(x);
	}
	bool is_avail() {
		return !status;
	}
	int get_people_num() {
		return Customer_list.size();
	}
	double get_average_time() {
		if (Customer_list.size() == 0)
			return 0;
		double average=0;
		list<Customer>::iterator iter = Customer_list.begin();
		for (; iter != Customer_list.end(); iter++) {
			average += iter->get_wait_time();
		}
		average = (double)average/Customer_list.size();
		return average;
	}
};
#endif // !Windows_hpp
#ifndef Event_hpp
#define Event_hpp
#define RP 100//Random maxmum
#include "random.hpp"
struct Event {
	int occur_time;//事件发生时间
	int type;// -1表示到达,只检索是否有空窗;属于[0,4]表示从0~4号窗口离开,置空闲

	Event(int time = get_random(RP), int type = -1) :
		occur_time(time),
		type(type){}
};
#endif // !Event_hpp
#include <iostream>
#include "System.hpp"
#include <ctime>

#include <list>
using namespace std;
int main()
{
	//srand(time(NULL));
	System exam(10000);
	exam.run();
}
#ifndef System_hpp
#define System_hpp
#include "Customer.hpp"
#include "Event.hpp"
#include "random.hpp"
#include "Windows.hpp"
#include <iomanip>
#include <list>
#include <vector>
#include <iostream>
using namespace std;
static int num = 1;
#define LT 99//至多办公时间(必在100内离开)
class System {
private:
	double AverageWaitTime;
	Windows wins[5];
	list<Event> event_list;
	list<Customer> customer_list;
	int current_time;
	long int total_time;
	Event* current_event;

	void customerArrived();//顾客到达
	void customerDone();//顾客离开
	int get_avail_windows();//检索可利用窗口
	
public:
	System(long int totaltime=10000) {
		AverageWaitTime = 0;
		Event begin(0);//第一个顾客到达
		event_list.push_back(begin);
		//Event out(get_random(10), 0);
		//event_list.push_back(out);
		current_time = 0;
		total_time = totaltime;
		current_event = &(*event_list.begin());
	}

	double get_AverageWaitTime() {
		return AverageWaitTime;
	}
	
	int get_current_time() {
		return current_time;
	}
	void run();//运行
	friend void insert_by_time(System& system, Event& event);//友元函数
};

void System::customerArrived() {
	current_time = current_event->occur_time;
	Customer x(num++, current_time);//生成一个顾客,到达时间为此事件发生时间,等待时间未设置
	Event arrive(current_time + get_random(9)+1);//平均n+1/2到一个人
	if (arrive.occur_time < total_time) {//(arrive.occur_time < total_time) 到达时间在关门前
		insert_by_time(*this,arrive);//在约定时间(关闭服务)前插入到达事件
	}
	if (get_avail_windows() == -1) {//窗口已满
		customer_list.push_back(x);//入顾客等待队列
	}
	else {//有空闲窗口
		int k = get_avail_windows();//获取空闲窗口
		int interim = get_random(LT)+1;//100单位时间内必定离开
		int time = interim + current_time;
		Event out(time, k);//生成离开事件
		insert_by_time(*this,out);//离开事件入队!!!得按照事件先后入队
		wins[k].redin_customer(x);
		wins[k].set_busy();
		
		cout << "Current Time:" << current_time << endl;
		cout << "Windows'num :"<<k+1<<"    "<<"Customer Num:" <<setw(5)<< x.get_num() << "     " << "Wait_time: " << setiosflags(ios::fixed) <<setprecision(5)<< x.get_wait_time() << endl;
	}
	event_list.pop_front();//任务完成则出队
	if (!event_list.empty())
		current_event = &(*event_list.begin());
	else
		current_event = NULL;
}
//要想获取当前客户离开的窗口,窗口由事件结构体(event)表示出来
void System::customerDone() {//顾客离开
	int k = current_event->type;
	wins[k].set_avail();
	current_time = current_event->occur_time;
	event_list.pop_front();
	if (!customer_list.empty()) {
		list<Customer>::iterator iter = customer_list.begin();
		iter->set_wait_time(current_time - iter->get_arrive_time());
		wins[k].redin_customer(*iter);
		wins[k].set_busy();
		//cout << "DONE1!"<< endl;
		cout << "Current Time:" << current_time << endl;
		cout << "Windows'num :" << k +1<< "    " << "Customer Num:" <<setw(5)<< iter->get_num() << "     " << "Wait_time: " << setiosflags(ios::fixed) << setprecision(5) << iter->get_wait_time() << endl;
		customer_list.pop_front();
		int time = current_time + get_random(LT)+1;//生成下个离开事件
		Event out(time, k);
		insert_by_time(*this, out);//生成离开事件
	}
	//event_list.pop_front();//任务出队 !!!  错误:这里出队会导致可能存在新加的出队任务排第一而被出队
	if (!event_list.empty())
		current_event = &(*event_list.begin());
	else
		current_event = NULL;
}
int System::get_avail_windows() {
	for (int i = 0; i < 5; i++) {
		if (wins[i].is_avail()) {
			return i;
		}
	}
	return - 1;
}
void System::run() {
	while (!event_list.empty()) {
		//只是增加顾客,不进入Done会导致不进入下一步动作
		if (current_event->type == -1)
			customerArrived();
		else
			customerDone();
	}
	cout << endl << endl;
	for (int i = 0; i < 5; i++) { 
		cout << "Windows'num :" << i +1<< "    " << "Average Wait Time: " << setiosflags(ios::fixed) <<setprecision(5)<<wins[i].get_average_time() <<"     Total Num of People:    "<<setw(5)<<wins[i].get_people_num()<< endl;
		AverageWaitTime += wins[i].get_average_time();
	}
	cout << "The Final Average Wait Time :" <<setprecision(5)<< AverageWaitTime / 5 << endl;
	return;
}
//插入链表,按照time排序,用于事件插入
void insert_by_time(System& system, Event& event) {
	list<Event>::iterator iter = system.event_list.begin();
	if (system.event_list.empty()) {
		system.event_list.push_back(event);
		return;
	}
	while (iter!=system.event_list.end()&& event.occur_time > iter->occur_time)
		iter++;
	system.event_list.insert(iter, event);
}
#endif // !System_hpp

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值