队列应用——循环分配器、银行服务模拟

1.循环分配器

  为在客户群体中共享某一资源(比如多个应用程序共享同一CPU),可以借助队列Q实现一个资源循环分配器。

RoundRobin{//循环分配器
    Queue Q(clients);//参与资源分配的所有客户组成队列Q
    while(!serviceClosed()){//在服务关闭之前,反复地
        e=Q.dequeue();//对首的客户出队,并
        serve(e);//接受服务,然后
        Q.enqueue(e);//重新入队
    }
}

  在以上轮值算法中,首先令所有参与资源分配的客户组成一个队列Q。接下来是一个反复轮回式的调度过程:取出当前位于对头的客户,将资源交给该客户使用;在经过固定的时间后,回收资源,并令该客户重新入队。得益于队列”先进先出”的特性,如此既可以在所有客户之间达到一种均衡的公平,也可以使得资源得以充分利用。这里每位客户持续占用资源的时间,对该算法的成败至关重要。一方面,为保证响应速度,这一时间值通常都不能过大。另一方面,因占有权的切换也需要耗费一定的时间,故若该时间值取得过小,切换过于频繁,又会造成整体效率的下降。因此,往往需要通过实测确定最佳值。

2.银行服务模拟

  通常,银行都设有多个窗口,顾客按到达的次序分别在各窗口排队等待办理业务。为此,可首先定义顾客类Customer如下,以记录顾客所属的队列及其所办业务的服务时长。

struct Customer{
    int window;unsigned int time;//顾客类:所属窗口(队列)、服务时长
}

  由simulate函数模拟顾客在银行中接受服务的整个过程:

void simulate{int nWin,int servTime){//按指定窗口数、服务总时间模拟银行业务
    Queue<Customer>* windows=new Queue<Customer>[nWin];//为每一窗口创建一个队列
    for(int now=0;now<servTime;now++){//在下班之前,每隔一个单位时间
        if(rand()%(1+nWin)){//新顾客以nWin/(nWin+1)的概率到达
            Customer c;c.time=1+rand()%98;//新顾客到达,服务时长随机确定
            c.window=bestWindow(windows,nWin);//找出最佳(最短)的服务窗口
            windows[c.window].enqueue(c);//新顾客加入对应的队列
        }
        for (int i=0;i<nWin;i++)//分别检查
            if(!windows[i].empty())//各非空队列
                if(--window[i].front().time()<=0)//队首顾客的服务时长减少一个单位
                    windows[i].dequeue();//服务完毕的顾客出列,由后继顾客接替
    }
    delete [] windows;//释放所有队列
}

  这里,首先根据银行所设窗口的数量相应的建立多个队列。以下以单位时间为间隔反复迭代,直至下班。每一时刻都有以为顾客按一定的概率抵达,随机确定所办业务服务时长之后,归入某一“最优”队列。每经单位时间,各队列最靠前顾客(如果有的话)的待服务时长均相应减少一个单位。若时长归零,则意味着该顾客的业务已办理完毕,故应退出队列并由后一位顾客(如果有的话)接替。可见,顾客归入队列和退出队列的事件可分别由enqueue()和dequeue()操作模拟,查询并修改队首顾客时长的事件则可由front()操作模拟。

  

int bestwindow(Queue<customer> winndows[],int nWin){//为新顾客确定最佳队列
    int minSize=winsows[0].size(),optiWin=0;//最佳队列(窗口)
    for(int i=1;i<nWin;i++)//在所有窗口中
        if(minSize>windows[i].size()){//挑选出
            minSize=windows[i].size();
            optiWin=i;//队列最短者
        }
    return optiWin;//返回
}

  为更好地为新到顾客确定一个队列,这里采用“最短优先”的原则。为此只需遍历所有的队列并通过size()接口比较其规模,即可找到其中的最短者。

原文地址:https://www.cnblogs.com/biwangwang/p/11335314.html

时间: 2024-10-16 04:05:14

队列应用——循环分配器、银行服务模拟的相关文章

数据结构Java实现07----队列:顺序队列&amp;顺序循环队列、链式队列、顺序优先队列

数据结构Java实现07----队列:顺序队列&顺序循环队列.链式队列.顺序优先队列 一.队列的概念: 队列(简称作队,Queue)也是一种特殊的线性表,队列的数据元素以及数据元素间的逻辑关系和线性表完全相同,其差别是线性表允许在任意位置插入和删除,而队列只允许在其一端进行插入操作在其另一端进行删除操作. 队列中允许进行插入操作的一端称为队尾,允许进行删除操作的一端称为队头.队列的插入操作通常称作入队列,队列的删除操作通常称作出队列. 下图是一个依次向队列中插入数据元素a0,a1,...,an-

数据结构6_顺序队列(循环队列)

本文实现了顺序队列,与链队列不同的是,顺序队列需要考虑一个问题, 问题情况如下, 解决办法:循环队列,当rear到分配的数组空间末尾时,转到数组头 但是当q.rear==q.front时,又如何区分一种是空队列,一种是满队列的情况呢 这里有两种方案 本次代码实现了第一种方法,同时设置了一个技术变量length,稍加改动便可实现第二个方法 代码如下: #include<iostream>using namespace std;//该顺序队列为循环队列,解决队尾指针达到最大值,队列中有空闲单元,但

队列与循环队列

复习一下队列与循环队列的实现(C语言) 1.单链队列: 1 typedef struct QNode{ //若不写typedef,在C中每次定义QNode需要在前面加上struct,而C++不必 2 QElemType data; 3 struct QNode *next; 4 }QNode,*QueuePtr; 5 6 typedef struct{ //若不写结构体名,则需要加上typedef 7 QueuePtr front; 8 QueuePtr rear; 9 }LinkQueue;

用循环与数组模拟双色球彩票中奖

String ji="机选"; String zi="自选"; System.out.println("请问机选还是自选?"); String my=wx.next(); int []a=new int[7];//用户买的号码记录的数组 //自选时的用户彩票 if(my.equals(zi)){ for(int i=0;i<a.length;i++){ //蓝球的输入 if(i==6){ System.out.println("请

二、数据结构之栈、队列、循环队列

二.数据结构之栈.队列.循环队列 顺序栈 Stack.h 结构类型,函数声明: #ifndef _STACK_H_ #define _STACK_H_ typedef int SElementType; ///顺序栈 #define STACK_INIT_SIZE 20 #define STACK_INCREMENT 10 typedef struct { SElementType * base; SElementType * top; int stackSize;///当前栈的大小 }SqSt

c语言描述-链式队列与循环队列

我真的不喜欢写代码 队列的特点 先进先出,即只能从队尾插入元素,从队头删除元素 队列的链式存储结构 #include<stdio.h> #include <stdlib.h> #include<malloc.h> typedef struct QNode { int date; struct QNode *next; }QNode ,*QueuePtr; typedef struct { int size; //记录队列长度 QueuePtr front; //头指针

队列之银行排号模拟

//CycQueue.h /* Queue:First In First Out (FIFO) 避免假溢出:使用循环队列. */ #define QUEUEMAX 20 //1.定义队列结构 typedef struct { DATA data[QUEUEMAX]; //队列数组 int head; //队头 int tail; //队尾 }CycQueue; //2.初始化队列 CycQueue *CycQueueInit() { CycQueue *q; if(q=(CycQueue *)m

3-08. 堆栈模拟队列(25)(ZJU_PAT 模拟)

题目链接:http://pat.zju.edu.cn/contests/ds/3-08 设已知有两个堆栈S1和S2,请用这两个堆栈模拟出一个队列Q. 所谓用堆栈模拟队列,实际上就是通过调用堆栈的下列操作函数: (1) int IsFull(Stack S):判断堆栈S是否已满,返回1或0: (2) int IsEmpty (Stack S ):判断堆栈S是否为空,返回1或0: (3) void Push(Stack S, ElementType item ):将元素item压入堆栈S: (4)

数据结构基础(5)--队列和循环队列详解--静态方式

队列的具体应用: 所有和事件有关的操作都有队列的影子. (例如操作系统认为先进来的先处理) 定义: 一种可是实现"先进先出"的存储结构 分类: 链式队列:用链表实现 静态队列:用数组实现 静态队列通常都必须是循环队列,为了减少 内存浪费. 循环队列 : 1.静态队列为什么必须是循环队列 如果用传统意义的数组实现队列,无论入队还是出队,rear和front指针只能+不能-: 比 F元素下标小的的数组元素下标就浪费了. 循环队列怎么用呢? 当出现这种情况时,如果仍然需要插入元素,那么f指向