C语言数据结构之离散事件模拟的实现代码(银行排队事件)

该博客介绍了一个使用C++实现的银行窗口服务系统,包括事件结构体、顾客结构体、队列和链表操作。系统通过事件表管理客户到达和离开,模拟四窗口服务,随机生成客户到达时间和业务处理时间。程序还包括了初始化、入队、出队等操作,以及事件的排序和插入。
摘要由CSDN通过智能技术生成

结果:结果
IDE:Visual Studio 2019
声明:为了方便书写代码,用到了C++的引用调用特性和iostream作为输入输出,读者可以使用指针调用和scanf_s/print语句实现相同效果
tips:有疑问可以在下面交流,我会尽量回复的

头文件heads.h

#pragma once
#include "stdio.h"
#include "iostream"
#include "time.h"
#define OK 1
#define TRUE 1
#define FALSE 0
#define ERROR 0
#define OVERFLOW -1
typedef short int Status;
using namespace std;
//事件的结构体
typedef struct {
	int Occurtime;
	int NType;
}Event,ElemType;
//顾客的结构体
typedef struct {
	int Arrivaltime;
	int Duration;
}Customer, QElemType;
//窗口前的顾客
typedef struct LNode {
	QElemType data;
	struct LNode* next;
}LNode,*Link;
//窗口
typedef struct {
	Link front, rear;
	int len;
}Cust;
//事件表
typedef struct Node{
	ElemType data;
	struct Node* next;
}*LinkList,*Eventlist,Node;
//程序主要变量
Eventlist ev;
Event en;
Cust q[5];
QElemType customer;
int TotalTime, CustomerNum, durtime, intertime;
int CloseTime = 480;//关门时间

头文件LNode.h

带头结点的链表,用来作为事件表,熟悉链表操作的建议不看

#include"heads.h"
//1.表的初始化
Status InitLNode(LinkList& L) {
	L = (LinkList)malloc(sizeof(LNode));
	L->next = NULL;
	return OK;
}//InitLNode
//2.销毁
Status DestoryLNode(LinkList& L) {
	LinkList p, q = L->next;
	while (q != NULL) {
		p = q->next;
		free(q);
		q = p;
	}
	L->next = NULL;
	return OK;
}//第一种写法
Status Destory(LinkList& L) {
	LinkList p;
	while (L->next != NULL) {
		p = L->next;
		L->next = p->next;
		free(p);
	}
	L->next = NULL;
	return OK;
}//第二种写法
Status Empty(LinkList L) {
	return (L->next == NULL) ? TRUE : FALSE;
}
//5.返回表的长度
Status Length(LinkList L) {
	int len = 0;
	LinkList head = L->next;
	while (head != NULL) {
		head = head->next;
		len++;
	}
	return len;
}
//6.查找第i个元素
Status GetDate(LinkList L, int i, ElemType& e) {
	LinkList p = L;
	for (; i > 0; i--) {
		if (!p->next)return ERROR;
		p = p->next;
	}
	e = p->data;
	return OK;
}
//7.按值查找
Status Locate(LinkList L, int& i, ElemType e) {
	i = 0;
	int j = 0;
	LinkList p, q = L;
	while (q->next != NULL) {
		p = q->next;
		q = p;
		i++;
		j = (p->data.Occurtime == e.Occurtime) ? i : NULL;
	}
	if (!j)return ERROR;
	return OK;
}
//8.按位置插入
Status InsertElem(LinkList& L, int i, ElemType e) {
	LinkList p, q = L;
	for (int j = 1; j < i; j++) {
		if (!q->next && j > i - 1) break;
		q = q->next;
	}
	p = (LinkList)malloc(sizeof(LNode));
	p->next = q->next;
	q->next = p;
	p->data = e;
	return OK;
}
//9.按位置删除
Status Delete(LinkList& L, int i, ElemType& e) {
	LinkList q, p = L;
	for (int j = 1; j < i; j++) {
		if (!p->next)return ERROR;
		p = p->next;
	}
	q = p->next;
	p->next = p->next->next;
	e = q->data;
	free(q);
	return OK;
}
//遍历事件表
Status Display(LinkList L) {
	LinkList p = L;
	while (1)
	{
		if (!p->next)break;
		p = p->next;
		cout <<"时间:"<< p->data.Occurtime << ",类型: "<<p->data.NType<<endl;
	}
	return OK;
}

头文件basicfunctions.h

队列结构,存储窗口前顾客的队列,熟悉队列结构的可以不看

#include "heads.h"
//初始化顾客队列
Status  InitQueue(Cust& Q) {
	Link q = (Link)malloc(sizeof(LNode));
	if (!q)return ERROR;
	Q.front = q;
	Q.rear = q;
	Q.len = 0;
	q->next = NULL;
	return OK;
}
//清空顾客队列
Status ClearQueue(Cust& Q) {
	if (Q.len == 0)return ERROR;
	Link q = Q.front->next,p;
	while (q); {
		p = q;
		q = q->next;
		free(p);
	}
	Q.rear = Q.front;
	Q.front->next = NULL;
	Q.len = 0;
	return OK;
}
//摧毁顾客队列
Status DestoryQueue(Cust& Q) {
	ClearQueue(Q);
	free(Q.front);
	return OK;
}
//判空
Status QueueEmpty(Cust Q) {
	if (Q.len == 0)return TRUE;
	return FALSE;
}
//返回长度
int QueueLength(Cust Q) {
	return Q.len;
}
//用e返回头元素
Status GetHead(Cust Q, QElemType& e) {
	if (Q.len == 0)return ERROR;
	e = Q.front->next->data;
	return OK;
}
//入队列
Status EnQueue(Cust& Q, QElemType e) {
	Link q = (Link)malloc(sizeof(LNode));
	if (!q)return ERROR;
	q->data = e;
	q->next = NULL;
	Q.rear->next = q;
	Q.rear = q;
	Q.len++;
	return OK;
}
//出队列
Status DeQueue(Cust& Q, QElemType& e) {
	if (Q.len == 0)return ERROR;
	Link q = Q.front->next;
	e = q->data;
	Q.front->next = q->next;
	free(q);
	Q.len--;
	if (Q.len == 0)Q.rear = Q.front;
	return OK;
}
//顾客访问
Status visit(QElemType e) {
	cout << "到达时间" << e.Arrivaltime << " 业务所需时间" << e.Duration << " ;";
	return OK;
}
//顾客队列访问
Status QueueTraverse(Cust Q, Status(*visit)(QElemType)) {
	Link q = Q.front->next;
	while (q) {
		visit(q->data);
		q = q->next;
	}
	cout << endl;
	return OK;
}

头文件Bank_Simulation.h

#include "basicfunctions.h"
#include "LNode.h"
//事件发生的时间比较
int cmp(Event a, Event b) {
	if (a.Occurtime >= b.Occurtime)return 1;
	return 0;
}
//四窗口前长度比较
int compare(int a, int b,int c,int d) {
	if (a < b) {
		if (a < c) {
			if (a < d)return 1;
			return 4;
		}
		if (c < d)return 3;
		return 4;
	}
	if (b < c) {
		if (b < d) return 2;
		return 4;
	}
	if (c < d)return 3;
	return 4;
}
int min(Cust c[]) {
	return compare(c[1].len, c[2].len, c[3].len, c[4].len);
}
//随机生成6-25的durtime和1-10的intertime
Status Random(int &durtime, int &intertime) {
	durtime = rand() % 20 + 6;
	intertime = rand() % 10 + 1;
	return OK;
}
//按发生时间插入事件表
Status OrderInsert(LinkList& L, Event e) {
	Node *p = L, *q=(Node*)malloc(sizeof(Node));
	if (!q)return OVERFLOW;
	q->data = e;
	while (p->next) {
		if(cmp(p->next->data, q->data))break;
		p = p->next;
	}
	q->next = p->next;
	p->next = q;
	return OK;
}
//一天的初始化
void OpenForDay() {
	TotalTime = 0; CustomerNum = 0;
	InitLNode(ev);
	en.Occurtime = 0; en.NType = 0;
	OrderInsert(ev, en);
	for (int i = 1; i < 5; i++)InitQueue(q[i]);
}
//处理客户到达事件
void CustomerArriverd() {
	Event e, f;
	++CustomerNum;
	Random(durtime, intertime);
	int t = en.Occurtime + intertime;
	if (t < CloseTime) {
		e.Occurtime = t;
		e.NType = 0;
		OrderInsert(ev, e);
	}
	customer.Arrivaltime = en.Occurtime;
	customer.Duration = durtime;
	int i = min(q);
	EnQueue(q[i], customer);
	if (QueueLength(q[i]) == 1) {
		f.Occurtime = en.Occurtime + durtime;
		f.NType = i;
		OrderInsert(ev, f);
	}
	Display(ev);
	cout <<""<< i << "号窗口顾客:";
	QueueTraverse(q[i], visit);
}
//处理客户离开事件
void CustomerDeparture() {
	Event e;
	int i = en.NType; DeQueue(q[i], customer);
	TotalTime += en.Occurtime - customer.Arrivaltime;
	if (!QueueEmpty(q[i])) {
		GetHead(q[i], customer);
		e.Occurtime = en.Occurtime + customer.Duration;
		e.NType = i;
		OrderInsert(ev, e);
	}
}
//事件
void Simulation() {
	OpenForDay();
	while (ev->next) {
		Delete(ev, 1, en);
		if (en.NType == 0) { 
			CustomerArriverd();
		}
		else CustomerDeparture();
	}
	cout << "The Average Time is:" << (float)TotalTime / CustomerNum;
}

源文件main.cpp

#include "Bank_Simulation.h"
int main(void) {
	srand((unsigned int)time(NULL));//取当前时间为随机数种子,确保多次运行的结果不一样
	Simulation();
}

因为自己是一边想一边写的,所以注释写的不是很好,有不懂或者我有错误的地方欢迎大家指正。

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值