队列

队列按照先进先出(First In First Out, FIFO)的规则管理数据。

操作

  • enqueue(x):在队列末尾添加元素x
  • dequeue():从队列开头取出元素

规则
数据中最先进入的队列的元素最先被取出。


以上都是队列的逻辑结构,队列的实现可以使用数组和链表。下面的例子将用数组来实现一个队列并进行操作。

以AOJ(Aizu Online Judge)中的一题多任务处理为例进行说明。题目链接 http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=ALDS1_3_B

There are \(n\) processes in a queue. Each process has \(name_i\) and \(time_i\). The round-robin scheduling handles the processes in order. A round-robin scheduler gives each process a quantum (a time slot) and interrupts the process if it is not completed by then. The process is resumed and moved to the end of the queue, then the scheduler handles the next process in the queue.

For example, we have the following queue with the quantum of 100ms.

A(150) - B(80) - C(200) - D(200)

First, process A is handled for 100ms, then the process is moved to the end of the queue with the remaining time (50ms).

B(80) - C(200) - D(200) - A(50)

Next, process B is handled for 80ms. The process is completed with the time stamp of 180ms and removed from the queue.

C(200) - D(200) - A(50)

Your task is to write a program which simulates the round-robin scheduling.

Input

\(n\) \(q\)
\(name_1\) \(time_1\)
\(name_2\) \(time_2\)
...
\(name_n\) \(time_n\)
In the first line the number of processes \(n\) and the quantum q are given separated by a single space.

In the following \(n\) lines, names and times for the \(n\) processes are given. \(name_i\) and \(time_i\) are separated by a single space.

Output

For each process, prints its name and the time the process finished in order.

Constraints
1 ≤ n ≤ 100000
1 ≤ q ≤ 1000
1 ≤ \(time_i\) ≤ 50000
1 ≤ length of \(name_i\) ≤ 10
1 ≤ Sum of \(time_i\) ≤ 1000000

Sample Input 1
5 100
p1 150
p2 80
p3 200
p4 350
p5 20
Sample Output 1
p2 180
p5 400
p1 450
p3 550
p4 800

题目大意是给出\(n\)个任务,名称和时间分别为\(name_i\)\(time_i\),这个任务排成一列,CPU按照循环调度法逐一处理这些任务,每次处理的时间为\(q\),没有处理完的任务排到队列的末尾,如此循环,直到所有任务处理完成。

我们这个时候就使用队列模拟循环调度法。没有使用Java中的集合类,而是使用数组来定义一个队列。主要需要定义的操作是出队和入队,需要定义的变量为队头指针和队尾指针。要注意的一点是定义队头和队尾指针时是指向的什么地方,比如队头指针指向开头的第一个元素,队尾指针指向最后一个元素,也可以定义为指向最后一个元素的后一个元素,这个可能会影响出队和入队的操作。定义之后按照自己定义的位置写相应的代码即可。

如果使用普通的数组操作,在一段时间之后队头队尾指针都会指向数组的末尾,这时就不能添加元素,空间也被浪费了。所以我们使用循环数组,本质也还是一个普通数组,只是在超出数组范围之后再从头开始,借助于取余操作来实现。使用循环数组后又出现了一个问题,我们无法区分队列的空与满,所以我们规定队列至少留一个空位(在判断队空和队满的情况下能体现出来)。

参考代码如下:

import java.util.Scanner;

class Task{
    String name;
    int time;
}

public class Main {

    static final int len = 100005;
    static Task[] num = new Task[len];

    static int head = 0;
    static int tail = 0;

    // 没有考虑队列满的情况
    public static void enqueue(Task task){
        num[tail] = task;
        tail = (tail+1) % len;
    }

    // 没有考虑队列空的情况
    public static Task dequeue(){
        Task temp = num[head];
        head = (head+1) % len;
        return temp;
    }

    public static void main(String[] args) {

        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int q = sc.nextInt();
        for (int i=0; i<n; i++){
            // 此处不能直接使用num[i].name,因为数组内放的是对象,对象的默认值为null,会抛出空指针异常。必须先创建对象
            Task temp = new Task();
            temp.name = sc.next();
            temp.time = sc.nextInt();
            enqueue(temp);
        }

        tail = n;

        int sum = 0;

        //当队列不为空时,我们进行下列操作
        while (head != tail){
            Task temp = dequeue();
            if (temp.time <= q){
                sum += temp.time;
                System.out.println(temp.name + " " + sum);
            }
            else {
                temp.time -= q;
                enqueue(temp);
                sum += q;
            }
        }
    }

}

转载于:https://www.cnblogs.com/WanJiaJia/p/7976117.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值