队列问题——银行排队

#include <iostream>
using namespace std;
//定义银行客户,Client作为队列的data域 
typedef struct client {
	int arrivalTime;//客户到达的时间
	int duration;//客户办理业务时间 
}Client;
//定义节点类型 
template <class DataType>
struct Node {
	DataType data;
	struct Node* next;
};
//定义队列类
template <class DataType>
class LinkQueue {
private:
	Node<DataType>* front, * rear;
	int length;
public:
	LinkQueue();//建立头结点,初始化属性 
	~LinkQueue();//释放队列空间 
	void enQueue(DataType x);//入队; 
	bool deQueue(DataType& item);//出队,item保存数据
	bool getFront(DataType& item);//获取队头元素到item所指单元 
	bool isEmpty();//判断队列是否为空
	void clearQueue();//清空队列
	void displayQueue();//显示队列内容
	int queueLength();//获取队列元素个数 
};
template <class DataType>
LinkQueue<DataType>::LinkQueue() {//有头节点方便 
	front = new Node<DataType>;//创建一个节点,将节点的地址赋给front
	front->next = NULL;
	rear = front;
	this->length = 0;
}
template <class DataType>
LinkQueue<DataType>::~LinkQueue() {//销毁队列 
	while (front) {
		Node<DataType>* p = front;
		front = front->next;
		delete p;
	}
}
template <class DataType>
void LinkQueue<DataType>::enQueue(DataType x) {//链式队列无需考虑满的问题,返回void; 
	Node<DataType>* s = new Node<DataType>;
	s->data = x;
	s->next = NULL;
	rear->next = s;
	rear = s;
	length++;
}
template <class DataType>
bool LinkQueue<DataType>::deQueue(DataType& item) {//需要考虑队列空的问题
	if (isEmpty()) {
		return false;
	}
	Node<DataType>* s = front->next;
	item = s->data;
	front->next = s->next;
	if (s->next == NULL) {
		rear = front;
	}
	delete s;
	length--;
	return true;
}
template <class DataType>
bool LinkQueue<DataType>::getFront(DataType& item) {
	if (isEmpty()) {
		return false;
	}
	else {
		item = front->next->data;
		return true;
	}
}
template <class DataType>
bool LinkQueue<DataType>::isEmpty() {
	if (front->next == NULL) {
		cout << "队列为空" << endl;
		return true;
	}
	else {
		return false;
	}
}
template <class DataType>
void LinkQueue<DataType>::clearQueue() {
	while (front->next) {
		Node<DataType>* s = front->next;
		front->next = s->next;
		if (s->next == NULL)
			rear = front;
		delete s;
		length--;
	}
}
template <class DataType>
void LinkQueue<DataType>::displayQueue() {
	Node<DataType>* p = front->next;
	while (p) {
		cout << "[" << p->data.arrivalTime << "," << p->data.duration << "] ";
		p = p->next;
	}
	cout << endl;
}
template <class DataType>
int LinkQueue<DataType>::queueLength() {
	return length;
}
//定义单个事件的结构体 
typedef struct evnode {
	int occurTime;//事件发生的时间
	int nType;//事件类型,-1表示到达事件,0-3表示四个窗口的离开事件;
	struct evnode* next;//指针域 
}evNode;
class EventList {
private:
	evNode* head;
public:
	EventList();//创建头结点 
	~EventList();//销毁链表
	bool isEmpty();
	void addNode(evNode ev);//插入节点要求按照occurTime从小到大排列 
	bool deleteNode(evNode* firstEv);
	void displayNode();
};
EventList::EventList() {
	head = new evNode;
	head->next = NULL;
}
EventList::~EventList() {
	evNode* p = head->next;
	while (p != NULL) {
		evNode* tmp = p;
		p = p->next;
		delete tmp;
	}
}
bool EventList::isEmpty() {
	if (head->next == NULL) {
		return true;
	}
	else {
		return false;
	}
}
void EventList::addNode(evNode ev) {
	evNode* node = new evNode;
	node->occurTime = ev.occurTime;
	node->nType = ev.nType;
	node->next = NULL;
	evNode* q;
	evNode* p;
	q = head;
	p = head->next;
	if (q->next == NULL) {
		head->next = node;
	}
	else {
		while (p != NULL) {
			if (p->occurTime > node->occurTime) {
				node->next = p;
				q->next = node;
				break;
			}
			else {
				q = p;
				p = p->next;
			}
		}
		if (p == NULL) {
			q->next = node;
		}
	}
}
bool EventList::deleteNode(evNode* firstEv) {
	if (isEmpty()) {
		return false;
	}
	evNode* p = head->next;
	head->next = p->next;
	firstEv->occurTime = p->occurTime;
	firstEv->nType = p->nType;
	delete p;
	return true;
}
void EventList::displayNode() {
	evNode* p = head->next;
	cout << "显示事件表:";
	while (p != NULL) {
		cout << "[" << p->occurTime << "," << p->nType << ",";
		if (p->next == NULL) {
			cout << "-" << "]";
		}
		else {
			cout << "^" << "]" << "->";
		}
		p = p->next;
	}
	cout << "\n";
}
int findMin(LinkQueue<Client> queue[], int n) {
	int* a = new int[n];
	int* b = new int[n];
	for (int i = 0; i < n; i++) {
		a[i] = queue[i].queueLength();
		b[i] = i;
	}
	for (int j = 0; j < n - 1; j++) {
		if (a[j] < a[j + 1]) {
			int temp = a[j];
			int temp2 = b[j];
			a[j] = a[j + 1];
			b[j] = b[j + 1];
			a[j + 1] = temp;
			b[j + 1] = temp2;
		}
	}
	int num = b[n - 1];
	delete[] b;
	return num;
}
const int CLOSE_TIME = 40;
double simulation() {
	int totalTime = 0;//为客户服务总时长 
	int customerNum = 0; //客户人数
	int chcount = 0;
	//定义队列数组queue,下标0至3分别表示4个排队窗口队列,-1表示是新客户到达事件 
	LinkQueue<Client> queue[4];
	//建立事件对象链表对象,设定第一个客户到达的事件
	EventList evList;
	//初始化事件列表,加入第一个节点,起始时间为0,第一个时间为-1(新客户到达事件)
	//设置evltem值为[0,-1,NULL];
	evNode evltem = { 0,-1,NULL };
	evList.addNode(evltem);
	//扫描并处理事件列表 
	while (!evList.isEmpty()) {
		chcount = chcount + 1;
		cout << "-------------------------第" << chcount << "次循环------------------" << endl;
		//删除事件链表中的第一个节点存入evltem
		evList.deleteNode(&evltem);
		cout << "删除链表中第一个节点存入" << evltem.occurTime << "," << evltem.nType << endl;
		if (evltem.nType == -1) {
			/*------新客户到达事件-------*/
			//客户人数加1
			customerNum++;
			cout << "是新客户到达事件,请输入durTime和interTime:" << endl;
			//输入随机数durTime和interTime 当前客户服务时间,
			//下一客户到达时间间隔时间 
			int durTime, interTime;
			cin >> durTime >> interTime;
			if (evltem.occurTime + interTime < CLOSE_TIME) {//在银行关门前进行服务 
				//设定下一客户到达的事件插入事件表
				evNode evTemp;
				evTemp.occurTime = evltem.occurTime + interTime;
				evTemp.nType = -1;
				evTemp.next = NULL;
				cout << "把下一个客户到达的事件插入事件表" << endl;
				evList.addNode(evTemp);
				evList.displayNode();
			}
			//排队人数最少的队列 
			int min = findMin(queue, 4);
			//当前客户进入排队人数最少的队列 
			Client client;
			client.arrivalTime = evltem.occurTime;
			client.duration = durTime;
			queue[min].enQueue(client);//入队	
			cout << "当前用户进入人数最少的队列:" << "queue" << min;
			queue[min].displayQueue();
			//如果当前客户到达的窗口没有人在排队(他是第一个客户)
			if (queue[min].queueLength() == 1) {
				//设定第一个客户离开银行的事件,插入时间表中
				evNode evTemp;
				evTemp.occurTime = evltem.occurTime + durTime;
				evTemp.nType = min;
				evList.addNode(evTemp);
				cout << "设定第一个客户离开银行的事件,插入时间表中" << endl;
				cout << "显示事件表:" << endl;
				evList.displayNode();
			}
		}
		else {
			//-----客户离开事件-------
			 //获得用户所在窗口号(队列号)
			int win = evltem.nType;
			//将当前要离开的客户从队列中删除,并将当前客户信息存入 client
			Client client;
			queue[win].deQueue(client);
			cout << "将当前要离开的客户从队列中删除" << client.arrivalTime << "," << client.duration << "queue" << win << endl;
			queue[win].displayQueue();
			//计算客户在银行逗留时间,把当前客户时间累加到totaltime
			totalTime = totalTime + client.duration;
			//如果还有人在排队,将队头客户离开事件插入事件表
			if (queue[win].queueLength() != 0) {
				cout << "如果还有人在排队,将队头客户离开事件插入事件表" <<
					//获取队头节点数据
					queue[win].getFront(client);
				//把队头节点的离开事件插入到时间表中
				evNode evTemp;
				evTemp.occurTime = evltem.occurTime + client.duration;
				evTemp.nType = win;
				cout << "如果还有人在排队,将队头客户离开事件插入事件表" << evTemp.occurTime << "," << evTemp.nType;
				evList.addNode(evTemp);
				cout << "显示事件表:";
				evList.displayNode();
			}
		}
	}
	//计算客户平均处理时间 
	return totalTime * 1.0 / customerNum;//返回客户平均处理时间 
}
int main() {
	//	23 4
	//	3 1
	//	11 3
	//	29 2
	//	18 4
	//	13 5
	//	20 30
	double time = simulation();
	cout << "客户在银行的平均逗留时间是:" << time;
}

参考B站懒猫老师数据结构课程 

【懒猫老师-数据结构-(12)队列应用:银行排队模拟(离散事件模拟)】https://www.bilibili.com/video/BV1nE411u7n4?vd_source=be8ba9904d4ffab80d462bfa61683299

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值