数据结构与算法——实验1:银行VIP窗口设计

数据结构与算法——实验1:银行VIP窗口设计

实验要求

模拟银行

实验内容:

基于课本p46给出的代码,实现以下功能。

1.VIP窗口窗口

在原有代码基础上添加VIP窗口功能,VIP窗口的出纳员只服务VIP用户,当VIP用户到达后可以
在本窗口按照到达先后顺序等待。

第1题约定

约定1号出纳员所在的1号窗口为VIP窗口,且银行中只有一个VIP窗口。
约定普通用户只能在普通窗口排队等候,其选择窗口的优先级为:空普通窗口>非空普通窗口。
约定用户排队过程中选定窗口后就会一直在该队列中等待,不会更换排队队伍。
约定用户之间无法感知对方是处理何种业务,不知道其业务所需的具体时间和剩余时间。
约定模拟时间外不产生用户到达事件,但是银行将会处理完所有用户到达事件。

第一问(10分)

第一问约定
约定VIP用户可以在普通窗口和VIP窗口排队等候,其选择窗口的优先级为:空VIP窗口>空普通窗口>非空VIP窗口>非空普通窗口。
本小题第一问将在去掉到达时间与服务时间随机化的情况下,对同学们的代码进行正确性验证。
验证内容是增设VIP窗口对服务情况产生的影响。
请同学们按照如下提示修改代码:

// event.h
enum isVip {notVip, Vip};
struct event
{
...
isVip isvip;
...
};
// event.h
InitEvent(...)
CompareEvent(...)
// ...
...

以下文所示输入为例,时间处于0、4、8时分别到达一名随机身份的顾客,银行将安排窗口为顾
客服务。对于8时到来的VIP用户,他所面临的的情况:在增设VIP窗口前,不区分顾客身份服
务,8时到来的顾客面对两个非空串口的情况下将会选择随机选择一个窗口进行服务,VIP身份
没有获得收益;在增设VIP窗口后,VIP用户在某些情况下可以比普通用户更快受到服务。

#用例1
#./bank
Enter the simulation time in minutes: 10
Enter the number of bank tellers: 2
Enter the range of arrival times in minutes: 4 4
Enter the range of service times in minutes: 9 9

分析下表(繁忙程度=实际服务时间/总服务时间):
到达到达队列情况列情况 总用用时 1号窗口繁忙程度号窗口繁忙程度 2号窗口繁忙程度号窗口繁忙程度
P、P、V(增设VIP窗口前)

P、P、V(增设VIP窗口后)

第二问(30分)

第二问约定
约定VIP用户可以在VIP窗口排队等候,或者在普通窗口队列中插队(即排到普通窗口队列最前面)。
约定插队的VIP用户在普通窗口中按照到达顺序先后进行排队。
约定VIP用户选择窗口的优先级为:空VIP窗口>空普通窗口>插队到普通窗口队列。
编程实现功能,不给出测试用例。

2.VIP限时等待

第2题约定
约定只有出纳员服务完当前用户后,才会重新计算所有排队的用户中的VIP用户的等待时间,如果等待时间已到达最长等待时间,将优先服务等待时间长的VIP用户。
约定等待时间满的VIP顾客,可以更换柜台服务。即所有柜台出纳员会按照等待时间由长到短的顺序服务所有队列中的VIP用户。(对于VIP用户而言,打破最初不能更换队伍的约定)
无VIP窗口情况下,银行规定,VIP用户等待时间不得超过X分钟,VIP用户与普通用户之间设置排队策略。
请同学们按照如下提示修改代码,使得VIP用户最多等待waitHigh时间。注意:出纳员只需要照顾本队列中的VIP用户。

printf("Enter the longest waitting time the customer can tolerate in minutes: ");
scanf("%d", &s->waitHigh);
第一问((40分)分)

实现功能

3.最佳排队机制(20分,酌情加分)

第3题约定
提示:如何决定三种等待时间的重要性?如何赋予不同的权重?如何在不同的权重设置下实现适宜的排队机制?请根据实验数据进行情况讨论。
本题为开放性思考题。
综合考虑各类角色等待时间:被VIP插队的用户越多,普通用户越不满;VIP等待的时间越长,VIP越不满;有人排队但有窗口闲置时,银行不满。
请通过实验数据说明如何设置排队机制可能是最优的。
建议:参考题目设置,逐步放开随机化的元素进行分析,可站在用户的角度或者银行的角度说明。
(请认真作答,自圆其说,合乎情理即可)

实验要求

阅读课本p49-p54页代码解析
按照实验内容完成1, 2题
思考并通过实验的形式完成第3题

ps:

收拾硬盘的时候无意间看到了这个曾经折磨我到半夜三点多的实验,出于让新人们参考的目的,在此将代码开源。(请叫我雷锋(✿◡‿◡))

本实验在原有代码基础上,增加了VIP窗口功能,VIP限时等待功能等,在本题目的条件中有较好的实现效果。

其中random.h对大部分注释做了翻译处理,在Event类里添加了vipIffo,以标志是否为VIP客户。在Simulation类里添加了用于随机产生VIP编号的函数Randomvip,对RunSimulation函数进行了大量的修改,以实现VIP的功能。

针对VIP窗口问题
1.创建事件(Event)对象时,将VIP客户的标志vipIffo传入事件对象(Event)中;
2.获取下一个空闲的柜台号时,对于VIP客户,会优先选择VIP专用柜员,即获取当前最早完成服务的VIP柜员编号;
3.对于VIP顾客,更新VIP柜员开始服务时间和完成服务时间,并生成离开事件;同时,在一般柜员队列中进一步寻找可用柜员。
针对VIP限时等待
Requeue 函数可以实现对于等待时间长且VIP属性为0的顾客重新加入队列,并重置其柜台号和等待时间。
针对最佳排队机制
这个部分就自己发挥吧~
综合考虑各类角色等待时间:被VIP插队的用户越多,普通用户越不满;VIP等待的时间越长,VIP越不满;有人排队但有窗口闲置时,银行不满。
综合以上部分考虑,可以设置VIP用户在所有用户中的比例,并按照比例设置相应数量的VIP窗口。

代码写得比较烂,但是绝对能跑,混个80分应该不是问题,建议还是自己改改。

代码仅供参考


random.h

#ifndef RANDOM_NUMBER_GENERATOR
#define RANDOM_NUMBER_GENERATOR

#include <time.h>

// 宏定义常量,用于生成随机数和更新种子
const unsigned long maxshort = 65536L;
const unsigned long multiplier = 1194211693L;
const unsigned long adder = 12345L;

class RandomNumber

{
	private:
    // 私有成员,保存当前的种子
    	unsigned long randSeed;
	public:
    // 构造函数,如果不提供种子,则使用系统时间作为种子
    	RandomNumber(unsigned long s = 0);

    // 生成随机整数,0 <= value <= n-1
    	unsigned short Random(unsigned long n);

    // 生成随机实数,0 <= value < 1.0
    	double fRandom(void);
};

// 构造函数,用于初始化随机数种子
RandomNumber::RandomNumber(unsigned long s)
{
    if (s == 0)
        randSeed = time(0); // 自动使用系统时间作为种子
    else
        randSeed = s;       // 使用用户提供的种子
}

// 生成指定范围内的随机整数
unsigned short RandomNumber::Random(unsigned long n)
{
    randSeed = multiplier * randSeed + adder;    // 用乘法和加法生成下一个随机数
    return (unsigned short)((randSeed >> 16) % n);    // 返回生成的随机数
}

// 生成 0 到 1 之间的随机实数
double RandomNumber::fRandom(void)
{
    return Random(maxshort) / double(maxshort); // 生成 0 到 maxshort-1 的随机整数,然后除以 maxshort 得到实数
}

#endif  

apqueue.h

#ifndef PRIORITYQUEUE_CLASS
#define PRIORITYQUEUE_CLASS

#include <iostream>
#include <stdlib.h>
using namespace std;
// maximum size of the priority queue array
const int MaxPQSize = 50;

class PQueue
{
private:
    // priority queue array and count
    int count;
    DataType pqlist[MaxPQSize];

public:
    // constructor
    PQueue(void);

    // priority queue modification operations
    void  PQInsert(const DataType& item);
    DataType PQDelete(void);
    void ClearPQ(void);

    // priority queue test methods
    int Requeue(int ID, int time, int NT, int servicetime);// here
    int PQEmpty(void) const;
    int PQFull(void) const;
    int PQLength(void) const;
};

// initialize priority queue count
PQueue::PQueue(void) : count(0)
{}

// insert item into the priority queue 
void PQueue::PQInsert(const DataType& item)
{
    // if all elements of pqlist are used, terminate the program
    if (count == MaxPQSize)
    {
        cerr << "Priority queue overflow!" << endl;
        exit(1);
    }
    // place item at the rear of the list and increment count
    pqlist[count] = item;
    count++;
}

// delete an element from the priority queue and return its value
DataType PQueue::PQDelete(void)
{
    DataType min;
    int i, minindex = 0;

    if (count > 0)
    {
        // find the minimum value and its index in pqlist
        min = pqlist[0];    // assume pqlist[0] is the minimum

        // visit remaining elments, updating minimum and index
        for (i = 1; i < count; i++)
            if (pqlist[i] < min)
            {
                // new minimum is pqlist[i]. new minindex is i
                min = pqlist[i];
                minindex = i;
            }
        // move rear element to minindex and decrement count
        pqlist[minindex] = pqlist[count - 1];
        count--;
    }
    // qlist is empty, terminate the program
    else
    {
        cerr << "Deleting from an empty priority queue!" << endl;
        exit(1);
    }
    // return minimum value 
    return min;
}
// return number of list elements
int PQueue::PQLength(void) const
{
    return count;
}

// test for an empty priority queue
int PQueue::PQEmpty(void) const
{
    return count == 0;
}

// test for a full priority queue
int PQueue::PQFull(void) const
{
    return count == MaxPQSize;
}

// clear the priority queue by resetting count to 0
void PQueue::ClearPQ(void)
{
    count = 0;
}

// 函数名称:Requeue
// 函数作用:将等待在某柜台前面的顾客重新加回队列,重置他们的柜台号和等待时间,并更新总服务时间
// 参数列表:
//   ID: int,当前空闲柜台的号码
//   time: int, 当前时间
//   NT: int,新的柜台号码
//   TSTTST: int,总服务时间
// 返回值:int, 更新后的总服务时间

int PQueue::Requeue(int ID, int time, int NT, int TSTTST)
{
    // 遍历所有事件对象,找到对应柜台的 departure 事件对象
    for (int i = 0; i < count; i++)
    {
        // 找到对应柜台的 departure 事件对象
        if (pqlist[i].GetTellerID() == ID && pqlist[i].GetVIP() == 0 && pqlist[i].GetEventType() == departure)
        {
            // 重置柜台号和等待时间
            pqlist[i].ChangeTheTeller(NT);
            pqlist[i].ChangeTheWaittime(time);

            // 更新总服务时间
            TSTTST -= pqlist[i].GetServiceTime();
        }
    }

    // 返回更新后的总服务时间
    return TSTTST;
}

#endif  // PRIORITYQUEUE_CLASS

sim.h

#ifndef SIMULATION_CLASS
#define SIMULATION_CLASS

#include <iostream>
#include <iomanip>
#pragma hdrstop

#include "random.h"     // include random number generator
using namespace std;
// specifies the two kinds of events
enum EventType { arrival, departure };

class Event {

private:
    int time;               // 事件发生时间
    EventType etype;        // 事件类型,到达或离开
    int customerID;         // 顾客编号
    int tellerID;           // 服务员编号
    int waittime;           // 等待时间
    int servicetime;        // 服务时间
    int vipIffo;            // 是否为VIP客户的标志

public:
    // 构造函数
    Event(void);
    Event(int t, EventType et, int cn, int tn, int wt, int st, int ifv);

    // 获取私有成员的方法
    int GetTime(void) const;
    EventType GetEventType(void) const;
    int GetCustomerID(void) const;
    int GetTellerID(void) const;
    int GetWaitTime(void) const;
    int GetServiceTime(void) const;
    int GetVIP(void);

    // 修改私有成员数据的方法
    void ChangeTheTeller(int newID);
    void ChangeTheWaittime(int newwait);
};

// 默认构造函数
Event::Event(void) {}

// 重载构造函数,用于初始化事件信息
Event::Event(int t, EventType et, int cn, int tn, int wt, int st, int ifv) :
    time(t), etype(et), customerID(cn), tellerID(tn), waittime(wt), servicetime(st), vipIffo(ifv)
{}

// 返回事件发生时间
int Event::GetTime(void) const {
    return time;
}

// 返回事件类型(到达或离开)
EventType Event::GetEventType(void) const {
    return etype;
}

// 返回顾客编号
int Event::GetCustomerID(void) const {
    return customerID;
}

// 返回服务员编号
int Event::GetTellerID(void) const {
    return tellerID;
}

// 返回顾客等待的时间
int Event::GetWaitTime(void) const {
    return waittime;
}

// 返回顾客需要服务的时间
int Event::GetServiceTime(void) const {
    return servicetime;
}

// 返回是否为VIP客户的标志
int Event::GetVIP(void) {
    return vipIffo;
}

// 修改服务员编号的方法
void Event::ChangeTheTeller(int newID) {
    tellerID = newID;
}

// 修改等待时间的方法
void Event::ChangeTheWaittime(int newwait) {
    waittime = waittime + newwait - time;
}

// 重载小于运算符,用于优先队列中排序
int operator< (Event e1, Event e2) {
    return e1.GetTime() < e2.GetTime();
}

// 定义数据类型为事件类型,用于优先队列
typedef Event DataType;
#include "apqueue.h"


// Structure for Teller Info    
struct TellerStats
{
    int finishService;      // when teller available
    int totalCustomerCount; // total of customers serviced
    int totalCustomerWait;  // total customer waiting time
    int totalService;       // total time servicing customers
    int ifonwork;
    int vipstarttime;
};


class Simulation
{
private:
    int simulationLength;        // 模拟的时间长度
    int numTellers;              // 柜台数
    int nextCustomer;            // 下一个顾客的 ID
    int arrivalLow, arrivalHigh; // 顾客到达时间区间
    int serviceLow, serviceHigh; // 服务时间区间
    int vipindex;                // VIP 顾客在队列中的位置
    TellerStats tstat[11];       // 记录每个柜台服务的顾客数量和总服务时间的结构体,最大支持 10 个柜台
    PQueue pq;                   // 普通顾客的优先队列
    PQueue vip;                  // VIP 顾客的优先队列
    RandomNumber rnd;            // 随机数生成器,用于产生顾客到达和服务的时间


    int NextArrivalTime(void);    // 计算下一个顾客到达时间
    int GetServiceTime(void);     // 随机生成当前顾客的服务时间
    int NextAvailableTeller(int vip); // 获取下一个空闲的柜台号
    int Randomvip(void);          // 随机产生一个 VIP 顾客的编号
public:
    // 构造函数
    Simulation(void);

    void RunSimulation(void);           // 执行模拟过程
    void PrintSimulationResults(void);  // 打印模拟结果
};

// constructor initializes simulation data and prompts client
// for simulation parameters
Simulation::Simulation(void)
{
    int i;
    Event firstevent;

    // Initialize Teller Information Parameters
    for (i = 1; i <= 10; i++)
    {
        tstat[i].finishService = 0;
        tstat[i].totalService = 0;
        tstat[i].totalCustomerWait = 0;
        tstat[i].totalCustomerCount = 0;
        tstat[i].ifonwork = 0;
        tstat[i].vipstarttime = 0;
    }
    nextCustomer = 1;
    vipindex = 0;
    // reads client input for the study
    cout << "Enter the simulation time in minutes: ";
    cin >> simulationLength;
    cout << "Enter the number of bank tellers: ";
    cin >> numTellers;
    cout << "Enter the range of arrival times in minutes: ";
    cin >> arrivalLow >> arrivalHigh;
    cout << "Enter the range of service times in minutes: ";
    cin >> serviceLow >> serviceHigh;

    // generate first arrival event
    // teller#/waittime/servicetime not used for arrival
    pq.PQInsert(Event(0, arrival, 1, 0, 0, 0, 0));
}

// determine random time of next arrival 
int Simulation::NextArrivalTime(void)
{
    return arrivalLow + rnd.Random(arrivalHigh - arrivalLow + 1);
}

// determine random time for customer service
int Simulation::GetServiceTime(void)
{
    return serviceLow + rnd.Random(serviceHigh - serviceLow + 1);
}

// return first available teller
int Simulation::NextAvailableTeller(int vip)
{
    // initially assume all tellers finish at closing time
    int minfinish = simulationLength;

    // assign random teller to customer who arrives
    // before closing but obtains service after closing
    int minfinishindex = rnd.Random(numTellers) + 1;
    if (!vip)
    {
        // find teller who is free first
        for (int i = 1; i <= numTellers; i++)
            if (tstat[i].finishService < minfinish)
            {
                minfinish = tstat[i].finishService;
                minfinishindex = i;
            }
    }
    else
    {
        for (int i = 1; i <= numTellers; i++)
        {
            if (tstat[i].vipstarttime < minfinish)
            {
                minfinish = tstat[i].vipstarttime;
                minfinishindex = i;
            }
        }
    }
    return minfinishindex;
}

int Simulation::Randomvip(void)
{
    return rnd.Random(2);
}
///



//***************修改*****************************修改***************************修改***********************//
void Simulation::RunSimulation(void)
{
    Event e, newevent; // 定义事件对象e和newevent
    int nexttime; // 下一个事件发生的时间
    int tellerID; // 处理顾客业务的服务员编号
    int servicetime; // 顾客所需服务的时间
    int waittime; // 顾客等待的时间

    // 进行事件循环,直到优先队列为空
    while (!pq.PQEmpty())
    {
        // 取出优先队列中优先级最高的事件
        e = pq.PQDelete();

        // 处理到达事件
        if (e.GetEventType() == arrival)
        {
            // 计算下一次到达事件的时间
            nexttime = e.GetTime() + NextArrivalTime();

            // 判断下一个到达事件是否超出总模拟时间,如果超出则只处理已有事件不再生成新事件
            if (nexttime > simulationLength)
                continue;
            else
            {
                // 生成下一个顾客的到达事件,并将其加入优先队列
                nextCustomer++;
                if (Randomvip())
                {
                    vipindex += 1;
                    newevent = Event(nexttime, arrival,
                        nextCustomer, 0, 0, 0, vipindex);
                    // 如果随机出的顾客是VIP,则加入VIP队列中
                }
                else
                    newevent = Event(nexttime, arrival,
                        nextCustomer, 0, 0, 0, 0);
                pq.PQInsert(newevent);
            }

            // 在控制台打印出顾客到达事件的信息:时间、顾客编号、是否为VIP
            cout << "Time: " << setw(2) << e.GetTime()
                << "  " << "arrival of customer "
                << e.GetCustomerID() << " vip:" << e.GetVIP() << endl;

            // 如果当前顾客不是VIP,则生成该顾客的离开事件,将其加入优先队列
            servicetime = GetServiceTime();
            if (!e.GetVIP())
            {
                // 找到空闲的服务员,更新服务员的状态
                tellerID = NextAvailableTeller(e.GetVIP());
                if (tstat[tellerID].finishService <= e.GetTime())
                    tstat[tellerID].finishService = e.GetTime();
                if (tstat[tellerID].finishService - e.GetTime() >= 0)
                    waittime = tstat[tellerID].finishService -
                    e.GetTime();
                else
                    waittime = 0;
                if (waittime == 0) tstat[tellerID].ifonwork = 1;
                tstat[tellerID].totalCustomerWait += waittime; // 更新服务员的统计信息
                tstat[tellerID].totalCustomerCount++;
                tstat[tellerID].totalService += servicetime;
                tstat[tellerID].finishService += servicetime;
                if (tstat[tellerID].ifonwork == 1)
                    tstat[tellerID].vipstarttime = e.GetTime() + servicetime; // 更新VIP的开始服务时间
                // 生成该顾客的离开事件,并将其加入优先队列
                newevent = Event(tstat[tellerID].finishService,
                    departure, e.GetCustomerID(), tellerID,
                    waittime, servicetime, e.GetVIP());
                pq.PQInsert(newevent);
            }
            else // 如果当前顾客是VIP
            {
                // 找到空闲的服务员,更新服务员的状态
                tellerID = NextAvailableTeller(e.GetVIP());
                if (tstat[tellerID].finishService <= e.GetTime())
                    tstat[tellerID].finishService = e.GetTime();
                if (tstat[tellerID].vipstarttime - e.GetTime() >= 0)
                    waittime = tstat[tellerID].vipstarttime -
                    e.GetTime();
                else
                {
                    waittime = 0;
                    tstat[tellerID].vipstarttime = e.GetTime();
                }
                tstat[tellerID].totalCustomerWait += waittime; // 更新服务员的统计信息
                tstat[tellerID].totalCustomerCount++;
                tstat[tellerID].totalService += servicetime;
                tstat[tellerID].finishService = tstat[tellerID].vipstarttime + servicetime;
                tstat[tellerID].vipstarttime = tstat[tellerID].finishService; // 更新VIP的开始服务时间

                // 生成该顾客的离开事件,并将其加入优先队列
                newevent = Event(tstat[tellerID].finishService,
                    departure, e.GetCustomerID(), tellerID,
                    waittime, servicetime, e.GetVIP());
                pq.PQInsert(newevent);

                // 如果服务员之前没有在工作状态,则将其加入仍在等待服务的顾客队列
                if (tstat[tellerID].ifonwork == 0)
                    tstat[tellerID].totalService = pq.Requeue(tellerID, tstat[tellerID].finishService, NextAvailableTeller(0), tstat[tellerID].totalService);
                tstat[tellerID].ifonwork = 1;
            }
        }

        // 处理离开事件
        else
        {
            tstat[e.GetTellerID()].ifonwork = 0; // 标记该服务员为非工作状态

            // 在控制台打印出顾客离开事件的信息:时间、顾客编号、是否为VIP,服务员编号,等待时间和服务时间
            cout << "Time: " << setw(2) << e.GetTime()
                << "  " << "departure of customer "
                << e.GetCustomerID() << " vip:" << e.GetVIP() << endl;
            cout << "       Teller " << e.GetTellerID()
                << "  Wait " << e.GetWaitTime()
                << "  Service " << e.GetServiceTime()
                << endl;

            // 找到当前事件对应的服务员的编号
            tellerID = e.GetTellerID();

            // 如果服务员在该事件发生时已经完成服务,则不需要更新服务员的状态
            //if (e.GetTime() == tstat[tellerID].finishService)
                //tstat[tellerID].finishService = 0;
        }
    }

    // 考虑服务员加班的情况,更新模拟结束时间
    simulationLength = (e.GetTime() <= simulationLength)
        ? simulationLength : e.GetTime();
}
// summarize the simulation results
void Simulation::PrintSimulationResults(void)
{
    int cumCustomers = 0, cumWait = 0, i;
    int avgCustWait, tellerWorkPercent;
    float tellerWork;

    for (i = 1; i <= numTellers; i++)
    {
        cumCustomers += tstat[i].totalCustomerCount;
        cumWait += tstat[i].totalCustomerWait;
    }

    cout << endl;
    cout << "******** Simulation Summary ********" << endl;
    cout << "Simulation of " << simulationLength
        << " minutes" << endl;
    cout << "   No. of Customers:  " << cumCustomers << endl;
    cout << "   Average Customer Wait: ";

    avgCustWait = int(float(cumWait) / cumCustomers + 0.5);
    cout << avgCustWait << " minutes" << endl;
    for (i = 1; i <= numTellers; i++)
    {
        cout << "    Teller #" << i << "  % Working: ";
        // display percent rounded to nearest integer value
        tellerWork = float(tstat[i].totalService) / simulationLength;
        tellerWorkPercent = int(tellerWork * 100.0 + 0.5);
        cout << tellerWorkPercent << endl;
    }
}

#endif  // SIMULATION_CLASS

Bank.cpp

#include "sim.h"

int main(void)
{
    // declare an object S for our simulation
    Simulation S;

    // run the simulation
    S.RunSimulation();

    // print the results
    S.PrintSimulationResults();

    return 1;
}
/*

<Run #1 of Program 5.7>

Enter the simulation time in minutes: 30
Enter the number of bank tellers: 2
Enter the range of arrival times in minutes: 6 10
Enter the range of service times in minutes: 18 20
Time:  0  arrival of customer 1
Time:  7  arrival of customer 2
Time: 16  arrival of customer 3
Time: 19  departure of customer 1
       Teller 1  Wait 0  Service 19
Time: 25  departure of customer 2
       Teller 2  Wait 0  Service 18
Time: 37  departure of customer 3
       Teller 1  Wait 3  Service 18

******** Simulation Summary ********
Simulation of 37 minutes
    No. of Customers:   3
    Average Customer Wait: 1 minutes
    Teller #1  % Working: 100
    Teller #2  % Working: 49

<Run #2 of Program 5.7>

Enter the simulation time in minutes  480
Enter the number of bank tellers  4
Enter the range of arrival times in minutes  2 5
Enter the range of service times in minutes  6 20

<arrival and departure of 137 customers>

******** Simulation Summary ********
Simulation of 521 minutes
    No. of Customers:  137
    Average Customer Wait: 2 minutes
    Teller #1  % Working: 89
    Teller #2  % Working: 86
    Teller #3  % Working: 83
    Teller #4  % Working: 86
    */

仅供参考哦~

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
一、 功能简介 本课件是一个动态演示数据结构算法执行过程的辅助教学软件, 它可适应读者对算法的输入数据和过程执行的控制方式的不同需求, 在计算机的屏幕上显示算法执行过程中数据的逻辑结构或存储结构的变化状况或递归算法执行过程中栈的变化状况。整个系统使用菜单驱动方式, 每个菜单包括若干菜单项。每个菜单项对应一个动作或一个子菜单。系统一直处于选择菜单项或执行动作状态, 直到选择了退出动作为止。 二、 系统内容 本系统内含84个算法,分属13部分内容,由主菜单显示,与《数据结构》教科书中自第2章至第11章中相对应。各部分演示算法如下: 1. 顺序表 (1)在顺序表中插入一个数据元素(ins_sqlist) (2)删除顺序表中一个数据元素(del_sqlist) (3)合并两个有序顺序表(merge_sqlist) 2. 链表 (1)创建一个单链表(Crt_LinkList) (2)在单链表中插入一个结点(Ins_LinkList) (3)删除单链表中的一个结点(Del_LinkList) (4)两个有序链表求并(Union) (5)归并两个有序链表(MergeList_L) (6)两个有序链表求交(ListIntersection_L) (7)两个有序链表求差(SubList_L) 3. 栈和队列 (1)计算阿克曼函数(AckMan) (2)栈的输出序列(Gen、Perform) (3)递归算法的演示  汉诺塔的算法(Hanoi)  解皇后问题的算法(Queen)  解迷宫的算法(Maze)  解背包问题的算法(Knap) (4)模拟银行(BankSimulation) (5)表达式求值(Exp_reduced) 4. 串的模式匹配 (1)古典算法(Index_BF) (2)求Next 函数值(Get_next)和按Next 函数值进行匹配 (Index_KMP(next)) (3)求 Next 修正值(Get_nextval)和按 Next 修正值进行匹配(Index_KMP(nextval)) 5. 稀疏矩阵 (1)矩阵转置 (Trans_Sparmat) (2)快速矩阵转置 (Fast_Transpos) (3)矩阵乘法 (Multiply_Sparmat) 6. 广义表 (1)求广义表的深度(Ls_Depth) (2)复制广义表(Ls_Copy) (3)创建广义表的存储结构(Crt_Lists) 7. 二叉树 (1)遍历二叉树  二叉树的线索化  先序遍历(Pre_order)  中序遍历(In_order)  后序遍历(Post_order) (2) 按先序建二叉树(CrtBT_PreOdr) (3) 线索二叉树  二叉树的线索化  生成先序线索(前驱或后继) (Pre_thre)  中序线索(前驱或后继) (In_thre)  后序线索(前驱或后继) (Post_thre)  遍历中序线索二叉树(Inorder_thlinked)  中序线索树的插入(ins_lchild_inthr)和删除(del_lchild_inthr)结点 (4)建赫夫曼树和求赫夫曼编码(HuffmanCoding) (5)森林转化成二叉树(Forest2BT) (6)二叉树转化成森林(BT2Forest) (7)按表达式建树(ExpTree)并求值(CalExpTreeByPostOrderTrav) 8. 图 (1)图的遍历  深度优先搜索(Travel_DFS)  广度优先搜索(Travel_BFS) (2)求有向图的强连通分量(Strong_comp) (3)有向无环图的两个算法  拓扑排序(Toposort)  关键路径(Critical_path) (4)求最小生成树  普里姆算法(Prim)  克鲁斯卡尔算法(Kruscal) (5)求关节点和重连通分量(Get_artical) (6)求最短路径  弗洛伊德算法(shortpath_Floyd)  迪杰斯特拉算法(shortpath_DIJ) 9. 存储管理 (1)边界标识法 (Boundary_tag_method) (2)伙伴系统 (Buddy_system) (3)紧缩无用单元 (Storage_compactio

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值