1.队列的定义
- 队列是一种先进先出的线性表。一端允许插入一端允许删除,允许插入的那端称为队尾,允许删除的那端称为对头
2.队列的实现:链队列
typedef int ElemType;
typedef struct QNode
{
ElemType data;
QNode* next;
}QNode,*Queueptr;
typedef struct
{
Queueptr front;
Queueptr rear;
}LinkQueue;
bool InitQueue(LinkQueue &queue)
{
queue.front = queue.rear = (Queueptr)malloc(sizeof(QNode));
if(queue.front) return false;
queue.front->next = nullptr;
return true;
}
bool DestroyQueue(LinkQueue &Q)
{
while(Q.front)
{
Q.rear = Q.front->next;
free(Q.front);
Q.front = Q.rear;
}
return true;
}
bool EnQueue(LinkQueue& Q,ElemType e)
{
Queueptr newNode = (Queueptr)malloc(sizeof(QNode));
newNode->data = e;
newNode->next = nullptr;
Q.rear->next = newNode;
Q.rear = newNode;
return true;
}
bool DeQueue(LinkQueue& Q,ElemType& e)
{
if(Q.front->Q.rear) return false;
Queueptr p = Q.front->next;
e = p->data;
Q.front->next = p->next;
if(p==Q.rear)
Q.rear = Q.front;
free(p);
}
3.循环队列——队列的顺序表示和实现
- 顺序表示和实现队列优势在于不用离散的分配内存节省内存方便管理,缺点是如果使用顺序表示普通队列导致头指针和尾指针不停地向前进,直到内存溢出,所以使用循环队列就很好的解决了问题
- 在顺序表示中也是头指针指向对尾,尾指针指向队伍尾的下一个指针,rear-front为队列大小。
- rear=front表示空队列,所以满队列不能用rear=front表示,解决办法是用rear+1 = front,即实际大小是maxsize-1
- 循环队列定义
#define MAXQSIZE 100
typedef int ElemType;
typedef struct
{
ELenType* base;
int front;
int rear;
}CQueue;
bool InitQueue(CQueue q)
{
q.base = (ElemType*)malloc(sizeof(ElemType));
if(!q.base) return;
q.front = q.rear = 0;
}
bool QueueLength(Queue Q)
{
return (Q.rear-Q.front+MAXQSIZE) % MAXQSIZE;
}
bool EnQueue(Queue& Q,ElemType e)
{
if((Q.rear+1) % MAXQSIZE)==Q.front) return false;
Q.base[rear] = e;
Q.rear = (Q.rear+1) % MAXQSIZE;
return true;
}
bool DeQueue(Queue& Q,ElemType e)
{
if(Q.front ==Q.rear) return false;
e = Q.base[Q.front];
Q.front = (Q.front+1)%MAXQIZE;
return true;
}
4.队列应用之离散事件
- 假设某银行有4个窗口对外接待客户,从早晨银行开门起不断有客户进入银行。由于每个窗口在某个时刻只能接待一个客户,因此在客户人数众多时需在每个窗口前顺次排队,对于刚进入银行的客户,如果某个窗口的业务员正空闲,则可上前办理业务;反之,若4个窗口均有客户所占,他便会排在人数最少的队伍后面。现在需要编制一个程序以模拟银行的这种业务活动并计算一天中客户在银行逗留的平均时间
- 我们称客户到达银行和离开银行这两个时刻发生的事情为“事件”,则整个模拟程序将按事件发生的先后顺序进行处理,这样一种模拟程序称为事件驱动模拟。
- 银行事件驱动模拟程序的定义
void Bank_Simulation(int CloseTime)
{
OpenForDay();
while(MoreEvent)
{
EventDrived(OccurTime,EventType)
switch(EventType)
{
case 'A':
CustomerArrivee();
break;
case 'D':
CustomerArrived();
break;
default:Invalid();
}
}
CloseForDay();
}
typedef struct
{
int OccurTime;
int NType;
}Event,ElemType;
typedef LinkList EventList;
typedef struct
{
int ArrivalTime;
int Duration;
}QElemType;
EventList ev;
Event en;
LinkQueue q[5];
QElemType customer;
int cmp(Event a,Event b);
{
if(a.OccurTime>a.OcurrTime)
return 1;
else if(a.OccurTime==a.OcurrTime)
return 0;
else
return -1;
}
void OpenForDay()
{
TotalTime = 0;CustomerNum=0;
InitList(ev);
en.OccurTime = 0;
en.NType = 0;
for(int i=1;i<=4;++i)
InitQueue(q[i]);
}
void CustomerArrived()
{
++CustomerNum;
Random(durtime,intertime);
t = en.OcurrTime + intertime;
if(t<CloseTime)
OrderInsert(ev,(t,0),cmp);
i = Minnum(q);
EnQueue(q[i],(en.OccurTime,durtime));
if(QueueLength(q[i])==1)
OrderInsert(en,(en.OccurTime+durtime,i),cmp);
}
void CustomerDepature()
{
i = en.NType;
DelQueue(q[i],customer);
TotalTime +=en.OccurTime-customer.ArrivalTime;
if(!QueueEmpty(q[i]))
{
GetHead(q[i],customer);
OrderInsert(ev,(en.OccurTime+curtomer.Duration,i),(*cmp)());
}
}
void Bank_Simulation(int CLoseTime)
{
OpenForDay();
while(!ListEmpty(ev))
{
DelFirst(GetHead(ev,p);
en = GetCurElem(p);
if(en.NType==0)
CustomerArrived();
else
CustomerDeparture();
}
cout<<(float)TotalTime/CustomerNum):
}