数据结构3.6 银行排队模拟问题 记录

  回顾使用链表写数据结构中的 银行排队模拟问题 其中遇到了个问题就是新建的队列,队列节点为结构体,有保存有下一个节点的指针,但是每次对队列进行插入删除操作后,调用printf函数都会破坏头指针里面保存的地址信息,现在初步考能够查找到的原因是可能在进行指针操作的时候并没有重新分配指针导致的局部变量还没有销毁之前,printf输出的时候覆盖了局部变量的地址导致[链接]http://bbs.csdn.net/topics/391744696)
  所以将代码做了重新做了优化,插入节点的时候做了重新分配新地址操作

待解决的问题
  • rand 随机函数的了解还不是太深
  • 其中的链表的操作还有待优化
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
typedef struct{
    int OccurTime; //发生时间
    int NType;//事件类型
}Event,ElemType;
typedef struct{
    Event *base;
    int size;
    int length;
}EventList;//事件链表
typedef struct{
    int ArrivalTime;//到达时间
    int Duration;//处理时间
}QElemType;//人员节点
typedef struct QNode{
    QElemType c;
    struct QNode* next;
}QNode;//排队节点
typedef struct{
    QNode * front;
    QNode * rear;
}LinkQueue;//队列节点
// 程序中用到的主要变量
EventList  ev;                // 事件表
Event      en;                // 事件
LinkQueue  q[5];              // 4个客户队列,q[0]未用
QElemType  customer;          // 客户记录
int TotalTime, CustomerNum;   // 累计客户逗留时间, 客户数
int CloseTime;

//---------------- 算法 3.7 ------------------
//-----------链表操作----------------------
//链表初始化
void InitList(EventList *ev);
void InsertList(EventList *ev,Event event,int (*cmpt)(Event a,Event b));
void printList(EventList ev);
int EmptyList(EventList ev);
Event GetHeadList(EventList ev);
int DelFirstList(EventList *el,Event *en);
//--------------队列操作--------------------------
int MinimumQueue(LinkQueue *q);
void InitQueue(LinkQueue *Q);
void EnQueue(LinkQueue *qL,QElemType qN);
int LengthQueue(LinkQueue Q);
void DeQueue(LinkQueue *Q,QElemType *customer);
int EmptyQueue(LinkQueue Q);
void GetHeadQueue(LinkQueue Q,QElemType * qN);
//--------工具函数--------------------
int cmp(Event a,  Event b);
void RandomT(int *durtime, int *intertime);
//-----------仓库排队的基本操作-------------------------
void CustomerDeparture();
void CustomerArrived();
void OpenForDay();
void Bank_Simulation(int closetime);
int main()
{
    Bank_Simulation(400);
    printf("Hello world!\n");
    return 0;
}
void Bank_Simulation(int closetime) {
    int i = 0;
    CloseTime = closetime;
    printf("Bank_Simulation( %d ) ----- 银行业务模拟\n", closetime);
    OpenForDay();                     // 初始化
    while (!EmptyList(ev))
    {
        printList(ev);
        if (DelFirstList(&ev, &en))
        {
            if (en.NType == 0)
            {
                CustomerArrived(); // 处理客户到达事件
            }else{
                CustomerDeparture();   // 处理客户离开事件
            }
        }
        if (++i % 9 == 0)
        {
            printf("\n----- 按任意键,继续 -----");
            getch();
            printf("\n\n");
        }
    }
    // 计算并输出平均逗留时间
    printf("\nThe Average Time is %f\n", (float)TotalTime/CustomerNum);
}; // Bank_Simulation
void OpenForDay() {
   // 初始化操作
   TotalTime = 0;
   CustomerNum = 0;  // 初始化累计时间和客户数为0

   // 初始化事件链表为空表
   InitList(&ev);

   en.OccurTime = 0;
   en.NType = 0;  // 设定第一个客户到达事件

   // 按事件发生时刻的次序插入事件表
   InsertList(&ev, en, cmp);
   int i=1;
   for (i=1; i<=4; ++i)
   {
       // 置空队列
       InitQueue(&q[i]);
   }
}; // OpenForDay
void CustomerArrived() {
    // 处理客户到达事件,en.NType=0
    int durtime, intertime, i, t;
    ++CustomerNum;
    printf("Customer %d arrived at %d and ", CustomerNum, en.OccurTime);
    RandomT(&durtime, &intertime);            // 生成随机数
    t = en.OccurTime + intertime;          // 下一客户到达时刻
    if (t<CloseTime)
    {
        Event ne = {t,0};// 银行尚未关门,插入事件表
        InsertList(&ev,ne, cmp);
    }

    i = MinimumQueue(q);                        // 求长度最短队列
    printf("enter the Queue %d\n", i);
    QElemType qe = {en.OccurTime,durtime};
    EnQueue(&q[i], qe);//MakeQElem(en.OccurTime, durtime)
    if (LengthQueue(q[i]) == 1) //设定第i队列的一个离开事件并插入事件表
    {
        Event ne =  {en.OccurTime+durtime,i};//en.OccurTime+durtime
        InsertList(&ev, ne, cmp);
    }

}; // CustomerArrived
void CustomerDeparture() {
  // 处理客户离开事件,en.NType>0
  printf("Customer departure at %d\n", en.OccurTime);
  int i = en.NType;
  DeQueue(&q[i], &customer); //删除第i队列的排头客户

  TotalTime += en.OccurTime-customer.ArrivalTime; // 累计客户逗留时间

  if (!EmptyQueue(q[i])) {   // 设定第i队列的一个离开事件并插入事件表
    GetHeadQueue (q[i], &customer);
    Event ne = {en.OccurTime+customer.Duration, i};//MakeElem(en.OccurTime+customer.Duration, i)
    InsertList(&ev, ne, cmp);
  }
}; // CustomerDeparture
//--------------链表操作--------------
void InitList(EventList *ev){
    ev->base = (Event*)malloc(1000*sizeof(Event));
    ev->size = 1000;
    ev->length = 0;
};
void InsertList(EventList *ev,Event event,int (*cmpt)(Event a,Event b))
{
    int i,j;
    Event NodeEvent;
    NodeEvent.NType = event.NType;
    NodeEvent.OccurTime = event.OccurTime;
    for(i=0;i<ev->length;i++)
    {
         if(event.NType == 0)
         {
            if(cmpt(ev->base[i],event)>0)
            {
                break;
            }
         }else{
            if(cmpt(ev->base[i],event)>=0)
            {
                break;
            }
         }
    }
    for(j=ev->length;j>i;j--){
        ev->base[j] = ev->base[j-1];
    }
    ev->base[i] = NodeEvent;
    ev->length++;
};
int EmptyList(EventList ev)
{
    if(ev.length ==0)
    {
        return 1;
    }
    return 0;
};
void printList(EventList ev)
{
    int i;
    for(i=0;i<ev.length;i++)
    {
            printf("->(%d,%d)",ev.base[i].NType,ev.base[i].OccurTime);
    }
    printf("\n");
}
Event GetHeadList(EventList ev)
{
    return ev.base[0];
};
int DelFirstList(EventList *el,Event *en)
{
    int i =0;
    *en = el->base[0];
    for(i=0;i<el->length;i++)
    {
        el->base[i]=el->base[i+1];
    }
    el->length--;
};
//----------------队列操作-----------------------
int MinimumQueue(LinkQueue *q) {  // 求长度最短队列
   int minlen = LengthQueue(q[1]);
   int i = 1,j;
   for ( j=2; j<=4; j++)
      if (LengthQueue(q[j]) < minlen) {
         minlen = LengthQueue(q[j]);
         i = j;
      }
   return i;
};
void InitQueue(LinkQueue *Q)
{
    QNode QN;
    QN.next = NULL;
    Q->front = Q->rear =(QNode *)malloc(sizeof(QNode));
    Q->front->next = NULL;
};
void EnQueue(LinkQueue *Q,QElemType qN){
    Q->rear->next = (QNode *)malloc(sizeof(QNode));
    Q->rear = Q->rear->next;
    Q->rear->c = qN;
    Q->rear->next = NULL;
};
int LengthQueue(LinkQueue Q)
{
    QNode *qp = Q.front;
    int i=0;
    while(qp->next)
    {
        i++;
        qp = qp->next;
    }
    return i;
};
void DeQueue(LinkQueue *Q,QElemType *customer)
{
    *customer = Q->front->next->c;
    Q->front->next = Q->front->next->next;
    if(!Q->front->next){
        Q->rear = Q->front;
    }

};
int EmptyQueue(LinkQueue Q)
{
    if(Q.front == Q.rear)
    {
        return 1;
    }else{
        return 0;
    }
};
void GetHeadQueue(LinkQueue Q,QElemType * qN)
{
    *qN = Q.front->next->c;
};
Event MakeElem(int occurTime,int type){
    Event eN;
    eN.NType = type;
    eN.OccurTime = occurTime;
    return eN;
};
QElemType MakeQElem(int occurTime,int durtime)
{
  QElemType qN;
  qN.ArrivalTime = occurTime;
  qN.Duration = durtime;
  return qN;
};
//----------------工具函数
int cmp(Event a,  Event b) {
  // 依事件a的发生时刻< 或= 或> 事件b的发生时刻分别返回-1或0或1
  if (a.OccurTime < b.OccurTime) return -1;
  if (a.OccurTime > b.OccurTime) return +1;
  return 0;
};

void RandomT(int *durtime, int *intertime) { // 生成随机数
   int r = rand()%10,t = rand()%10;
   *durtime = r<2?r+2:r;
   *intertime = t;
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值