银行客户一天平均访问时间离散模拟

正如标题所示的意思,该程序的目的是要模拟,银行客户办理业务所花费的平均时间。
该程序是事件驱动程序,按照事件驱动的思路进行。如此,首先需要建立一个事件列表,其中存储着按事件发生的时间顺序排列的事件,根据客户到银行的特点,可以发现,事件分为两种,1、客户到达银行事件。2、客户办理完事物离开银行事件。
为事件链表创建数据类型,数据类型我创建为结构体类型,因为对每个客户来说,一个客户到来就相当于是一个对应的事件,那么这个事件的数据类型就是该客户的基本特征,如此定义客户事件到来的时刻occursTime(可以是到来事件,也可以是离开事件),时间的类型。
创建银行办理业务的窗口队列,假设有四个。为队列添加数据类型,也为结构体类型,此时保存的是到来客户的到来时间arrividTime客户业务处理所要花费的时间durTime,客户排队需要花费的时间waiteTime,
接下来是创建处理这两种事件的事件处理方法,
对客户到来事件处理方法customerArrived():
1)、新客户到达银行事件的预测发生时间与该客户的时间间隔interTime,
2)、生成当前事件对应客户处理业务需要花费的事件
3)、将该事件的信息放入最短的队列中
4)、如果该队列只有该客户一个信息那么就给该客户添加一个离开事件,并添加到事件链表中。
对客户离开事件处理方法CustomerDeparture():
1)、计算总时间
2)、删除该离开事件对应的队列中的客户信息
3)、如果删除完这个信息后该队列后面仍有其他信息,那么就为该信息添加离开事件,并添加到事物链表中
上述是该事件驱动程序的核心方法,自然还有一些其他的方法,比如要是时间链表中的时间按时间顺序排列,那么就需要添加一个排序方法。在模拟程序执行中需要有初始化方法。等等其他直接上代码
以下是事件驱动程序的原理图:
这里写图片描述
下面分享我的源代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections;


namespace ListTable
{
    class Bank_Simulation
    {
         public  struct _event
        {
            public  int occurTime;//事件的开始时刻
            public int  nType;//事件类型
         };//定义事件的结构类型
         public  struct _queue
        {
            public int arrivalTime;//该顾客要离开的时刻,即为occurTime+durTime
            public int durTime;//顾客到达处理业务所需要的时间
            public int waiteTime;//排队等待时间
         };
        //创建事件链表
        private LinkList<_event> ev = new LinkList<_event>();
        //创建队列
        private QueueLink<_queue>[] qu = new QueueLink<_queue>[4];
        private int[] timer = new int[4];//创建数组用来对应个队列 当前下一个要来的客户 需要排队等待的时间
        private _event en;//用来承接当前处理事件
        private int closeTime;//银行关门时间
        private int totalTime;//顾客的总时间
        private int customerNum;//顾客数量
        public Bank_Simulation(int closeTime=50,int totalTime=0,int customer=0)
        {
            this.closeTime = closeTime;
            this.totalTime = totalTime;
            this.customerNum = customer;
            en = new _event();
            for(int i = 0; i < 4; i++)
            {
                qu[i] = new QueueLink<_queue>();
                timer[i] = 0;
            }
        }


        //本程序是事件驱动程序,故而函数的核心是围绕着事件列表处理的


        //创建程序的主函数
        public void BankSimulation()
        {
            Console.WriteLine("今日银行办理业务客户平均时间为:");

            //执行初始化函数
            OpenForDay();
            while (!ev.IsEmpty())
            {
                en = ev[0];//获取事件链表的头结点
                ev.DeleteAtIndex(0);//同时删除该结点
                if (en.nType == 0)//如果此事件类型为0,即客户到来事件
                {
                    //执行事件到来处理函数
                    CustomerArrived();
                }
                else//否则 即该事件为客户离开事件
                {
                    //执行客户离开的时间处理函数
                    CustomerDeparture();
                    Console.WriteLine("客户离开事件执行");
                }
               Console.WriteLine("当前事件链表中事件个数:"+ ev.GetLength());
            }
            //计算输出最终的计算结果
            Console.WriteLine(totalTime.ToString() );
            Console.WriteLine(customerNum.ToString());
            Console.WriteLine(totalTime/customerNum);
        }



        //初始化函数
        void OpenForDay()
        {
            //主要的目的是初始化一些基本的数据,时间表,队列,
            //同时将预测的第一个客户到达事件添加到时间表中
            _event temp = new _event();
            temp.occurTime = 0;//规定第一个客户到达的时刻为0
            temp.nType = 0;//初始化事件类型为到达事件
            ev.Add(temp);
            //程序要求 事件表中的数据是按照发生时刻的先后顺序排列的 所以应该执行一个排序方法,
            //但是此处是初始化 就一个结点所以就没必要了
        }

        //客户到达事件处理函数
        void CustomerArrived()
        {
            //主要功能如下
            //将顾客数量加1
            //执行客户达到,应该完成的操作
            //预见距离下一个客户到达的时间间隔intertime,生成当前客户的业务处理花费时间durtime
            //将预见的下一个客户到达事件 添加到事件表中
            //将当前客户添加到最短的队列中(即把客户必要的信息传递到队列中),
            //同时判断当前客户是否处于队首 若处于队首,那么就将为客户 设置离开事件 并添加到事件列表中
            customerNum++;
            Random rd = new Random();
            int interTime = rd.Next(1, 10);
            int durtime = rd.Next(1, 10);
            int t = en.occurTime + interTime;
            //创建预见的客户将到达的事件 并添加到事件表中

            if (t < closeTime)
            {
                _event temp1 = new _event();
                temp1.occurTime = t;
                temp1.nType = 0;
                ev.Add(temp1);
                Sorting(ev);
                Console.WriteLine("客户到达事件执行");

            }

            //当前事件处理
            //当前事件客户添加到 队列中
            _queue temp2 = new _queue();
            temp2.arrivalTime = en.occurTime;//客户离开时间
            temp2.durTime = durtime;
            //判断4个队列中最短的队列
            int i = MinQu(qu);
            temp2.waiteTime = timer[i];//该用户插入该队列要排队等待的时间
            qu[i].EnQueue(temp2);//该到达客户信息插入队列
            timer[i] += temp2.durTime;//计算当下一个客户到来时要等待的时间
            if (qu[i].GetLength() == 1)
            {//长度为1 为队首 添加离开事件 同时添加到事件列表中
                Console.WriteLine("添加离开事件");
                _event temp3 = new _event();
                temp3.occurTime = qu[i].GetHead().arrivalTime + qu[i].GetHead().durTime+qu[i].GetHead().waiteTime;
                temp3.nType = i;
                ev.Add(temp3);
                //此时应该有对事件表进行排序的算法
                Sorting(ev);
            }
        }
        private int MinQu(QueueLink<_queue>[] q)
        {
            int minLength = 0;
            for(int i = 0; i < 3; i++)
            {
                if (q[minLength].GetLength() > q[i + 1].GetLength())
                {
                    minLength = i + 1;
                }
            }
            return minLength;
        }
        private void  Sorting(LinkList<_event> eve)
        {//冒泡排序法
            for(int j = 0; j < eve.GetLength() - 1; j++)
            {
                for(int i = 0; i < eve.GetLength() - 1 - i; i++)
                {
                    if (eve[i].occurTime > eve[i + 1].occurTime)
                    {
                        eve.ChangeAtIndex(i, i + 1);//调用我内置到链表函数的交换方法
                    }
                }
            }
        }
        //执行客户离开事件
        private void CustomerDeparture()
        {
            totalTime += en.occurTime - qu[en.nType].GetHead().arrivalTime;
            Console.WriteLine("当前队列长度" + qu[en.nType].GetLength());
            timer[en.nType] -= qu[en.nType].GetHead().durTime;//当该队头的客户业务办理完了要走了,那么下一个要到来的客户等待时间就应该减去他 办理业务的时间
            qu[en.nType].DeQueue();//删除该离开事件对应的队列中的客户
            if (!qu[en.nType].IsEmpty())
            {//若该队列不为空 那么将队首元素设置一个离开事件
                Console.WriteLine("当前队列长度:" + qu[en.nType].GetLength());

                _event temp = new _event();
                temp.occurTime = qu[en.nType].GetHead().arrivalTime + qu[en.nType].GetHead().durTime+qu[en.nType].GetHead().waiteTime;//求得该事件的离开时刻
                temp.nType = en.nType;
                ev.Add(temp);
                Sorting(ev);
            }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值