《数据结构》严蔚敏 离散时间模拟——银行排队 算法3_6 - 3_7

这个是借鉴了一下别人的代码的。原文:https://www.cnblogs.com/kangjianwei101/p/5225738.html(膜大佬)
这个问题综合性很高,把队列和链表的知识都照顾到了诶。
学习一下~

还是先放截图吧
在这里插入图片描述


3.6.h


#ifndef _3_6_H
#define _3_6_H

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<time.h> //provide seed

#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define OVERFLOW -2
#define INDEFINE -3


#define SleepTime 1
#define DurationTime 20 // business time in a row 
#define IntervalTime 10 // last customer come 

typedef int Status;

//when a variable value is certain,could use enum
typedef enum 
{
	Arrive,Leave_1,Leave_2,Leave_3,Leave_4

}EventType;

typedef struct 
{
	int OccurTime;
	EventType NType;
	
}Event;

typedef Event LElemType_L;

typedef struct LNode
{
	LElemType_L data;
	struct LNode * next;
}LNode;

typedef LNode* LinkList;
typedef LinkList EventList;

typedef struct 
{
	int ArrivedTime;
	int Duration;
	int Count;
	
}QElemType_L;

typedef struct QNode //队列也是要有下一个的
{
	QElemType_L data;
	struct QNode *next;
}QNode;

typedef QNode* QueuePtr;

typedef struct 
{
	QueuePtr front;
	QueuePtr rear;
	
}LinkQueue;

//global variable

int gTotalTime,gCustomerNum;
int gCloseTime = 10;
EventList gEv;
Event gEn;
LinkQueue gQ[5];
QElemType_L gCustomerRcd;

//functions

void Bank_Simulation_1();

void OpenForDay();

Status MoreEvent();

void EventDrived(char * event);

void CustomerArrived();

void CustomerDeparture();

void Invalid();

void CloseForDay();

int cmp(Event a,Event b);

void Random(int *durtime,int *intertime);

Status OrderInsert(EventList gEv,Event gEn,int(cmp)(Event,Event));

int Minimum();

void Show();

void Bank_Simulation_2();


#endif


3.6.c


#include "3_6.h"

void
Show()
{
	int i ;
	QueuePtr p;
	for(i = 1;i<=4;i++)
	{
		for(p = gQ[i].front; p ; p = p->next)
		{
			if(p == gQ[i].front)
			{
				if(i == 1)
					printf("first: ⭕️");
				if(i == 2)
					printf("second:⭕️");
				if(i == 3)
					printf("third: ⭕️");
				if(i == 4)
					printf("forth: ⭕️");
			}
			else
				printf(" (%03d) ",p->data.Count);

			if(p == gQ[i].rear)
				printf("\n");
		}

	}

	sleep(SleepTime);
	printf("\n");

}

void
Random(int *durtime,int *intertime)
{
	srand((unsigned)time(NULL));
	*durtime = rand()%DurationTime+1;
	*intertime = rand()%IntervalTime+1;
}


int
cmp(Event a,Event b)
{
	if(a.OccurTime < b.OccurTime)
		return -1;
	if(a.OccurTime == b.OccurTime)
		return 0;
	if(a.OccurTime > b.OccurTime)
		return 1;
	return INDEFINE;
}


Status
InitList_L(LinkList *L)
{
	(*L) = (LinkList)malloc(sizeof(LNode));
	if(!(*L))
		exit(OVERFLOW);
	(*L)->next = NULL;

	return OK;
}


Status
ListEmpty_L(LinkList L)
{
	if( L != NULL && L->next == NULL)
		return TRUE;
	else
		return FALSE;

}

Status
ListDelete_L(LinkList L,int i,LElemType_L *e)
{
	LinkList pre,p;
	int j;

	pre = L;
	j = 1;

	while(pre->next && j<i)
	{
		pre = pre->next;
		++j;
	}

	if(!pre->next || j > i)
		return ERROR;

	p = pre->next;
	pre->next = p->next;
	*e = p->data;

	free(p);

	return OK;
}

Status
InitQueue_L(LinkQueue *Q)
{
	(*Q).front = (*Q).rear = (QueuePtr)malloc(sizeof(QNode));
	if(!(*Q).front)
		exit(OVERFLOW); 

	(*Q).front->next = NULL;

	return OK;

}

int
QueueLength_L(LinkQueue Q)
{
	int count = 0;
	QueuePtr p = Q.front;

	while(p != Q.rear)
	{
		count++;
		p = p->next;
	}

	return count;
}

Status
EnQueue_L(LinkQueue *Q,QElemType_L e)
{
	QueuePtr p;

	p = (QueuePtr)malloc(sizeof(QNode));
	if(!p)
		exit(OVERFLOW);

	p->data = e;
	p->next = NULL;

	(*Q).rear->next = p;
	(*Q).rear = p;

	return OK;
}

Status
DeQueue_L(LinkQueue *Q,QElemType_L *e)
{
	QueuePtr p;

	if( (*Q).front == (*Q).rear )
		return ERROR;

	p = (*Q).front->next;
	*e = p->data;

	(*Q).front->next = p->next;
	if((*Q).rear == p)
		(*Q).rear = (*Q).front;

	free(p);

	return OK; 

}

Status
QueueEmpty_L(LinkQueue Q)
{
	if(Q.front == Q.rear)
		return TRUE;
	else
		return FALSE;
}

Status
GetHead_L(LinkQueue Q,QElemType_L *e)
{
	QueuePtr p;
	if(Q.front == Q.rear)
		return ERROR;
	p = Q.front->next;
	*e = p->data;

	return OK;

}

int 
Minimum()
{
	int i1 = QueueLength_L(gQ[1]);
	int i2 = QueueLength_L(gQ[2]);
	int i3 = QueueLength_L(gQ[3]);
	int i4 = QueueLength_L(gQ[4]);

	if( i1<=i2 && i1<=i3 && i1<=i4 )
		return 1;
	if( i2<i1 && i2<=i3 && i2<=i4 )
		return 2;
	if( i3<i1 && i3<i2 && i3<=i4 )
		return 3;
	if( i4<i1 && i4<i2 && i4<i3 )
		return 4; 
	return INDEFINE;
}


Status
OrderInsert(EventList gEv,Event gEn,int(cmp)(Event,Event)) 
{
	int i;
	EventList p,pre,s;

	pre = gEv;
	p = gEv->next; // 因为链表带头节点,所以p指向第一个事件

	while(p && cmp(gEn,p->data) == 1) //查找事件gEn在时间表中插入的位置
	{
		pre = p;
		p = p->next;
	}

	s = (LinkList)malloc(sizeof(LNode));
	if(!s)
		exit(OVERFLOW);

	s->data = gEn;
	s->next = pre->next;
	pre->next = s;

	return OK;

}

void
OpenForDay()
{
	int i;

	gTotalTime = 0;
	gCustomerNum = 0;

	InitList_L(&gEv);//为什么要用struct LNode ** 呀
	//这里用的都是指向指针的指针!!!
	//用二级指针的原因:
	//一级指针作为函数参数可以交换两个数的值,
	//二级指针作为函数参数可以改变一级指针的值,也就是改变地址。
 
	gEn.OccurTime = 0;
	gEn.NType = Arrive;

	OrderInsert(gEv,gEn,cmp);

	for(i = 1;i <= 4;i++)
	{
		InitQueue_L(&gQ[i]); // 同样的疑问
	}

	Show();       //最后再写
} 


Status
MoreEvent()
{
	if(!ListEmpty_L(gEv))
		return TRUE;
	else
		return FALSE;
}

void
EventDrived(char *event)
{
	ListDelete_L(gEv,1,&gEn);

	if(gEn.NType == Arrive)
		*event = 'A';
	else
		*event = 'D';
}

void
CustomerArrived()
{
	int durtime,intertime;
	int cur_LeftTime,suc_ArrivalTime;
	int i;

	++gCustomerNum;

	Random(&durtime,&intertime);

	cur_LeftTime = gEn.OccurTime + durtime;
	suc_ArrivalTime = gEn.OccurTime + intertime;

	gCustomerRcd.ArrivedTime = gEn.OccurTime;
	gCustomerRcd.Duration = durtime;
	gCustomerRcd.Count = gCustomerNum;

	i = Minimum(); 
	EnQueue_L(&gQ[i],gCustomerRcd); //用户加入最短的队列

	Show();

	if(suc_ArrivalTime < gCloseTime)
	{
		gEn.OccurTime = suc_ArrivalTime;
		gEn.NType = Arrive;
		OrderInsert(gEv,gEn,cmp);
	}

	if(QueueLength_L(gQ[i]) == 1)
	{
		gEn.OccurTime = cur_LeftTime;
		gEn.NType = i;
		OrderInsert(gEv,gEn,cmp);
	}


}


void
CustomerDeparture()
{
	int i = gEn.NType;

	DeQueue_L(&gQ[i],&gCustomerRcd);

	Show();

	gTotalTime = gEn.OccurTime - gCustomerRcd.ArrivedTime;

	if(!QueueEmpty_L(gQ[i]))
	{
		GetHead_L(gQ[i],&gCustomerRcd);
		gEn.OccurTime += gCustomerRcd.Duration; 
		gEn.NType = i;
		OrderInsert(gEv,gEn,cmp); 
	}
}

void
Invalid()
{
	printf("wrong!\n");
	exit(OVERFLOW);
}

void
CloseForDay()
{
	printf("Today have %d customers,The Average Time is %f\n",
		gCustomerNum, (float)gTotalTime / gCustomerNum);
}




void 
Bank_Simulation_1()
{
	char eventType;

	OpenForDay();

	while(MoreEvent())
	{
		EventDrived(&eventType);

		switch(eventType)
		{
			case 'A':
				CustomerArrived();
				break;
			case 'D':
				CustomerDeparture();
				break;
			default:
				Invalid(); 
		}
	}

	CloseForDay();
}





void Bank_Simulation_2()
{
	OpenForDay();
	while(!ListEmpty_L(gEv))
	{
		ListDelete_L(gEv,1,&gEn);

		if(gEn.NType == Arrive)
			CustomerArrived();
		else
			CustomerDeparture();
	}
}




int main(int argc, char const *argv[])
{
	Bank_Simulation_1();

	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_37414405/article/details/86286395