离散xxx.cpp

来自「数据结构中离散事件的实现」· C++ 代码 · 共 342 行

CPP
342
字号
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
typedef struct linkqueue linkqueue;  
typedef int qelemtype; 
typedef struct qnode qnode;
typedef struct event event;
typedef struct eventlist eventlist;
struct event
{
	int occertime;  //事件发生时刻
	int ntype;      //事件类型,0表示到达事件,1至4表示四个窗口的离开事件
	event *next;
};
struct eventlist   //事件表
{
	event *front;   //队头指针 
};
//以下是对队列的一系列操作定义 
struct qnode   
{
	qelemtype data[2]; //data中的两个分别是"到达的时间"和"办理事务所需的时间"
    qnode *next;
};

struct linkqueue   //排队表
{
	qnode *front;  //队头指针
	qnode *rear;   //队尾指针
};

int listempty(eventlist ev) //是空的返回1,不是返回0
{
    if(ev.front==NULL)
		return 1;
	else
		return 0;
};

event *delist(eventlist &ev)  //若队列不空,则删除q的队头元素,用e返回其值.否则打印栈已空
{
	event *e;
	if(ev.front==NULL)
	{	
		printf("事件链表已空!");
		return 0;
	}
	else
	{
		//printf("%d",ev.front->ntype);
		//printf("%d",ev.front->occertime);
		e=ev.front;
        ev.front=ev.front->next;
		return (e);
	}
}

void initqueue(linkqueue &q)  //构造一个空队列q
{
	q.rear=q.front=(qnode*)malloc(sizeof(qnode));
	if(!q.front)
		printf("存储分配失败!");
	else
		q.front->next=NULL;

}

void destroyqueue(linkqueue &q)  //销毁队列q
{
    qnode *tmp;   //***
	while(q.front!=NULL)
	{
		tmp=q.front;
		q.front=q.front->next;
		free(tmp);
	}
}

void enqueue(linkqueue &q,qelemtype e[2])  //插入元素e为q的新的队尾元素   
{
	qnode *p=(qnode *)malloc(sizeof(qnode));
	if(!p)
		printf("存储分配失败!");
	else
	{
		p->data[0]=e[0];
		p->data[1]=e[1];   //?????
		p->next=NULL;
	    q.rear->next=p;//***
		q.rear=p;
	}
}

void dequeue(linkqueue &q,qelemtype e[2])  //若队列不空,则删除q的队头元素,用e返回其值.否则打印栈已空
{//***传地址,要不然改不了
	qnode *p;
	if(q.front==q.rear)
		printf("栈已空!");
	else
	{
		p=q.front->next;
		e[0]=p->data[0];
	    e[1]=p->data[1];
		q.front=p;
	}
}

int queueempty(linkqueue &q)  //若队列q为空队列,则返回1,否则返回0
{
	if(q.front->next==NULL)
		return 1;//****
	else
		return 0;

}


int queuelength(linkqueue q) //返回q的元素个数,即为队列的长度
{
	int length=0;
	qnode *tmp=q.front;
	while(tmp!=q.rear)
	{
		tmp=tmp->next;
		length++;
	}
	return length;
}


void gethead(linkqueue q,int a[2])  //若队列不空,则返回q的队头元素,否则返回0
{
	if(q.front->next==NULL)
	{
		printf("队列为空!");
	}
	else
	{
		a[0]=q.front->data[0];
		a[1]=q.front->data[1];
	}
}

// 以上是对队列的一系列基本操作的定义




eventlist ev;    //事件表,用来记录发生的事,它是由en按occertime的大小组成的
linkqueue q[5];  //4个客户队列,它是由customer[2]组成的			//***
int customer[2];   //客户记录,要有两个元素,一个是记录到达时间arrivaltime,一个是记录办理事务所需的时间duration
int totaltime;     //累计客户逗留时间
int customernum;   //客户数
int closetime=100;
int durtime;

int minimum (linkqueue q[5])//***
{
	int i, min,minlen;
    min=1;
	minlen=queuelength(q[1]);
	for(i=2;i<=4;i++)
	{
		if(queuelength(q[i])<minlen)
		{
			minlen=queuelength(q[i]);
			min=i;
		}
	}
	return min;
}


/*int random(int dtime,int intertime)   //它是可以生成随机数的函数
{
	printf("请给出随机的两个时间:\n");
    printf("办理事务所需的时间durtime: ");
	scanf("%d",&dtime);
	printf("离下一个客户的到达时间intertime: ");
	scanf("%d",&intertime);
}*/
int random1(int dtime)   //它是可以生成随机数的函数
{
	printf("请给出随机的两个时间:\n");
    printf("办理事务所需的时间durtime: ");
	//scanf("%d",&dtime);
	dtime=rand()%15+5;
	printf("%d\n",dtime);
	return dtime;
}
int random2(int intertime)   //它是可以生成随机数的函数
{
	printf("离下一个客户的到达时间intertime: ");
	//scanf("%d",&intertime);
	intertime=rand()%5+3;
	printf("%d\n",intertime);
	return intertime;
}

int cmp(event *a,event *b)  //依事件a,b的发生时间的先后来返回-1,0,1.  
{
	if(a->occertime>b->occertime)
	{
		return 1;
	}
	else if(a->occertime<b->occertime)
	{
		return -1;
	}
	else 
	{
		return 0;
	}
}

void orderinsert(eventlist &ev, int a[2])  //把a[2]插入事件表ev中,并且要按照e.occertime的先后顺序来排列.注意,ev只是一个活链表 ??????
{
	event *e=(event *)malloc(sizeof(event));
	event *p1,*p2;
	e->occertime=a[0];
	e->ntype=a[1];
	if(listempty(ev))
	{
		ev.front=e;
		ev.front->next=NULL;
	}
	else
	{
		if(cmp(ev.front,e)!=-1)  //比第一件事发生的还先//***
		{
			e->next=ev.front;
			ev.front=e;
		}
		else   
		{
            // printf("\nna er\n");
			for(p2=ev.front;p2->next!=NULL;p2=p2->next);
			if(cmp(p2,e)!=1)    //比最后一件事发生的还迟
			{
				p2->next=e;
				e->next=NULL;
				//printf("zhe er\n");
            }  
			else
			{
				for(p2=p1=ev.front;p1!=NULL;p2=p1,p1=p2->next)  //处于中间位置//***
				{
					if(cmp(p1,e)!=-1)//***
					{
						e->next=p1;
			            p2->next=e;
			            break;
					}
 
				}
			}
		}
	}
}


void initlist(eventlist q)  //构造一个空队列q
{
	q.front =NULL;//***
}

void openforday()   //初始化操作
{
	int i;
	totaltime=0;    //初始化累计时间
	customernum=0;  //初始化客户数
	initlist(ev);   //初始化事件链表为空表
    int	a[2]={0,0};     //设第一个客户的到达事件 a.occertime=0;  a.ntype=0;
    orderinsert(ev,a);  //插入事件表
	for(i=1;i<=4;i++)
		initqueue(q[i]);   //置空队列,初始化队列为空
}

void customerarrived(event *en)   //处理客户到达事件,en.ntype=0
{
	int t,i;                      
    int a[2];                    //相当于int durtime,intertime;   
	++customernum;
    a[0]=random1(a[0]);        //生成随机数---办理事务所需的时间durtime,    它和下一步相加相当于random(durtime,9intertime)
	a[1]=random2(a[1]);        //生成随机数---离下一个客户的到达时间intertime.
	t=en->occertime+a[1];      //下一个客户到达时刻
	if(t<closetime)
	{
	    int	a1[2]={t,0};  //这里的a1[2]是用来插入事件表的下一个客户到达事件,t为他的发生事件,0表示是到达事件 
		//printf("nextcustomerarrived"); 
	    orderinsert(ev,a1);
	}
	i=minimum(q);   //求长度最短的队列,返回它的组数
	int a2[2]={en->occertime,a[0]};  //a2为要插入队列的用户,t表示到达时间,a[0]表示处理用时
	printf("A customer arrived at %d and go to queue %d\n",en->occertime,i);
	enqueue(q[i],a2);   //把a2插入q[i]中
	if(queuelength(q[i])==1)     //表明为队列有且只有一个客户在 
	{
        int	a3[2]={en->occertime+a[0],i};
	    orderinsert(ev,a3);   //设定第i队列的一个离开事件并插入事件表 
	}
}

void customerdeparture(event *en)    //处理客户离开事件,en.type>0
{
	int i;   //组数
	i=en->ntype;  
	dequeue(q[i],customer);    //删除第i个队列的排头客户
    totaltime+=en->occertime-customer[0]; //累计客户逗留时间,customer[0]是用户到达时间arrivaltime
	printf("A customer departure at %d from queue %d\n",en->occertime,i);
    if(!queueempty(q[i]))      //如果第i队列不为空,设定一个离开事件并插入事件表
	{
		gethead(q[i],customer);
		int	a[2]={en->occertime+customer[1],i};
	    orderinsert(ev, a);
	}  
}


void main()
{
	event *p;
	openforday();  //初始化
	while(!listempty(ev))  //只要事件列表不空就继续循环
	{
		p=delist(ev);
		if(p->ntype==0)
			customerarrived(p); //处理客户到达事件
		else                       
			customerdeparture(p);     //处理客户离开事件 
	}
	  //计算并输出平均逗留时间
	printf("the average time is %0.3f\n",(float)totaltime/customernum);
}







⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?