(A卷,100分)- 打印机队列(Java & JS & Python)

题目描述

有5台打印机打印文件,每台打印机有自己的待打印队列。

因为打印的文件内容有轻重缓急之分,所以队列中的文件有1~10不同的代先级,其中数字越大优先级越高

打印机会从自己的待打印队列中选择优先级最高的文件来打印。

如果存在两个优先级一样的文件,则选择最早进入队列的那个文件。

现在请你来模拟这5台打印机的打印过程。

输入描述

每个输入包含1个测试用例,

每个测试用例第一行给出发生事件的数量N(0 < N < 1000)。

接下来有 N 行,分别表示发生的事件。共有如下两种事件:

  1. “IN P NUM”,表示有一个拥有优先级 NUM 的文件放到了打印机 P 的待打印队列中。(0< P <= 5, 0 < NUM <= 10);
  2. “OUT P”,表示打印机 P 进行了一次文件打印,同时该文件从待打印队列中取出。(0 < P <= 5)。

输出描述

  • 对于每个测试用例,每次”OUT P”事件,请在一行中输出文件的编号
  • 如果此时没有文件可以打印,请输出”NULL“。
  • 文件的编号定义为”IN P NUM”事件发生第 x 次,此处待打印文件的编号为x。编号从1开始。

用例

输入 7
IN 1 1
IN 1 2
IN 1 3
IN 2 1
OUT 1
OUT 2
OUT 2
输出 3
4
NULL
说明
输入 5
IN 1 1
IN 1 3
IN 1 1
IN 1 3
OUT 1
输出 2
说明

题目解析

本题可以基于优先队列实现打印机总是打印优先级最高的文件。

优先队列,如果想简单一点的话,则可以基于有序数组实现,但是有序数组是整体有序,每次有新任务入队,都需要O(n)时间复杂度维持。

优先队列最好是基于堆结构实现,所谓堆结构,即一颗完全二叉树。本题是优先级数值越大,优先级越高,因此我们可以使用大顶堆。

关于基于堆结构实现优先队列,可以参考

JavaScript算法源码

基于有序数组实现优先队列

/* JavaScript Node ACM模式 控制台输入获取 */
const readline = require("readline");

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
});

const lines = [];
let n;
rl.on("line", (line) => {
  lines.push(line);

  if (lines.length === 1) {
    n = parseInt(lines[0]);
  }

  if (n && lines.length === n + 1) {
    lines.shift();

    const tasks = lines.map((line) => line.split(" "));

    getResult(tasks);

    lines.length = 0;
  }
});

function getResult(tasks) {
  const print = {};

  let taskId = 1;
  for (let i = 0; i < tasks.length; i++) {
    const [type, printId, priority] = tasks[i];

    if (type === "IN") {
      const arr = [taskId, priority, i]; // i 是先来后到的顺序
      if (!print[printId]) {
        print[printId] = []; // 基于数组实现优先队列
      }
      print[printId].push(arr);
      print[printId].sort((a, b) => (a[1] != b[1] ? b[1] - a[1] : a[2] - b[2])); // 维持高优先级在头部,如果优先级相同,则按先来后到
      taskId++;
    } else {
      if (!print[printId] || print[printId].length == 0) {
        console.log("NULL");
      } else {
        const arr = print[printId].shift();
        console.log(arr ? arr[0] : "NULL");
      }
    }
  }
}

Java算法源码

Java已经有优先队列实现类PriorityQueue,因此可以直接使用它。

import java.util.HashMap;
import java.util.PriorityQueue;
import java.util.Scanner;

public class Main {
  public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);

    int n = Integer.parseInt(sc.nextLine());
    String[][] tasks = new String[n][];

    for (int i = 0; i < n; i++) {
      String[] s = sc.nextLine().split(" ");
      tasks[i] = s;
    }

    getResult(tasks);
  }

  public static void getResult(String[][] tasks) {
    // print中存放每台打印机的等待队列
    HashMap<String, PriorityQueue<int[]>> print = new HashMap<>();

    // 文件的编号定义为”IN P NUM”事件发生第 x 次,此处待打印文件的编号为x。编号从1开始。
    int x = 1;
    for (int i = 0; i < tasks.length; i++) {
      String[] task = tasks[i];
      // IN,OUT都有type和printId
      String type = task[0];
      String printId = task[1];

      if ("IN".equals(type)) {
        // IN还有priority
        String priority = task[2];
        // arr是打印任务
        int[] arr = {x, Integer.parseInt(priority), i}; // i代表先来后到的顺序
        // 为打印机printId设置打印优先级,打印任务的priority越大,优先级越高
        print.putIfAbsent(
            printId,
            new PriorityQueue<>(
                (a, b) ->
                    a[1] != b[1] ? b[1] - a[1] : a[2] - b[2])); // 优先按priority,如果priority相同,按先来后到i
        // 将打印任务加入对应打印机
        print.get(printId).offer(arr);
        x++;
      } else {
        // 打印机等待队列中取出优先级最高的打印任务arr
        if (!print.containsKey(printId) || print.get(printId).isEmpty()) {
          // 如果此时没有文件可以打印,请输出”NULL“。
          System.out.println("NULL");
        } else {
          int[] arr = print.get(printId).poll();
          if (arr != null) System.out.println(arr[0]); // arr[0]是x
          else System.out.println("NULL");
        }
      }
    }
  }
}

Python算法源码

import queue

# 输入获取
n = int(input())

tasks = []
for i in range(n):
    tasks.append(input().split())


class Task:
    def __init__(self, taskId, priority, index):
        """
        :param taskId: 任务ID
        :param priority: 任务优先级
        :param index: 任务到达顺序
        """
        self.taskId = taskId
        self.priority = priority
        self.index = index

    def __lt__(self, other):
        if self.priority != other.priority:
            return self.priority > other.priority
        else:
            return self.index < other.index


# 算法入口
def getResult(tasks):
    printer = {}

    taskId = 1
    for i in range(len(tasks)):
        task = tasks[i]

        type = task[0]
        printerId = task[1]

        if type == "IN":
            priority = task[2]
            if printer.get(printerId) is None:
                printer[printerId] = queue.PriorityQueue()
            printer[printerId].put(Task(taskId, int(priority), i))
            taskId += 1
        else:
            if printer.get(printerId) is None or printer[printerId].qsize() == 0:
                print("NULL")
            else:
                t = printer[printerId].get()
                print(t.taskId)


getResult(tasks)

免责声明:

1、IT资源小站为非营利性网站,全站所有资料仅供网友个人学习使用,禁止商用
2、本站所有文档、视频、书籍等资料均由网友分享,本站只负责收集不承担任何技术及版权问题
3、如本帖侵犯到任何版权问题,请立即告知本站,本站将及时予与删除下载链接并致以最深的歉意
4、本帖部分内容转载自其它媒体,但并不代表本站赞同其观点和对其真实性负责
5、一经注册为本站会员,一律视为同意网站规定,本站管理员及版主有权禁止违规用户
6、其他单位或个人使用、转载或引用本文时必须同时征得该帖子作者和IT资源小站的同意
7、IT资源小站管理员和版主有权不事先通知发贴者而删除本文

0

评论0

站点公告

没有账号?注册  忘记密码?