【蓝桥杯】十四招式冲刺之 “第二招”《队列》

前言

-🏀大家好,我是BXuan,热爱编程与篮球的软件工程大二学生一名
-📚近期在准备4月份的蓝桥省赛,本章与大家一起聊聊有关队列的问题!如文有误,请大家指出并多多包涵。
-🏃‍放弃不难,但坚持一定很酷。


🚩知识点

  • 普通队列实现原理与应用
  • 循环队列实现原理与应用

🚩概念

如果说链表和顺序表是对数据的存取位置的组织方式,那么队列就是一种对于存取方式限制的组织方式。换一种方式描述的话就是,队列既可以采用链表来表示,也可以采用数组(线性表)来表示,我们限制的是对于存放数据的存取方式。
在这里插入图片描述

🚩存储方式

顺序存储

在这里插入图片描述

链式存储

在这里插入图片描述

🚩队列

🌑队列的逻辑操作

  • 队列:只允许在一端进行插入操作,而另一端进行删除操作的线性表。
  • 空队列:不含任何数据元素的队列。
  • 允许插入(也称入队、进队)的一端称为队尾
  • 允许删除(也称出队)的一端称为队头
    在这里插入图片描述

🌓队列的操作特性

先进先出(FIFO)

🌕循环队列

逻辑上是首尾相连的数组,可是在数组中其实不存在这样的数组,所以在物理实现上是不存在的。

1.循环队列的实现方法

我们可以用取模的方法将其实现:

  • tail=(tail+1)% MAXSIZE

  • head=(head+1) % MAZSIZE

2.关于循环队列必须要解决的问题

  1. 出队时判断循环队列队为空

    队空:head == tail 跟线性队列一样。

  2. 出队时判断循环队列队为满

    队满:(tail+1) mod QueueSize==head

  3. 获得循环队列中的元素个数

    length = (tail - head + QueueSize) % QueueSize;

由于顺序存储队列必须预先确定一个固定的长度,所以存在存储元素个数的限制和空间浪费的问题,循环队列可以减少此问题的出现

🚀真题巩固

一、CLZ的银行(普通队列)

问题描述

CLZ 银行只有两个接待窗口,VIP 窗口和普通窗口,VIP 用户进入 VIP 窗口排队,剩下的进入普通窗口排队。现有 M 次操作,操作有四种类型,如下:

  • IN name V:表示一名叫 name 的用户到 VIP 窗口排队
  • OUT V:表示 VIP 窗口队尾的用户离开排队
  • IN name N:表示一名叫 name 的用户到普通窗口排队
  • OUT N:表示普通窗口队尾的用户离开排队

求 M 次操作结束后 VIP 窗口队列和普通窗口队列中的姓名。

要求:使用普通队列实现该题

输入描述

第一行是一个整数 M(1≤M≤1000),表示一共有 M 次操作。

第二行到第 M+1 行输入操作,格式如下:

  • IN name V
  • OUT V
  • IN name N
  • OUT N

输出描述

输出 M 次操作后 VIP 窗口队列和普通窗口队列中的姓名(从头到尾),先输出 VIP 窗口队列后输出普通窗口队列。

运行限制

  • 最大运行时间:1s
  • 最大运行内存: 128M

输入输出示例

输入:
5
IN xiaoming N
IN Adel V
IN laozhao N
OUT N
IN CLZ V
输出:
Adel
CLZ
laozhao

代码示例

package E_lanqiao;

import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改

public class Main {
    //主函数
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        //在此输入您的代码...
        Queue<String> vipQueue = new LinkedList<>();
        Queue<String> nQueue = new LinkedList<>();

        int M = scan.nextInt();// 表示M种操作
        scan.nextLine();// 吸收换行符

        while(M > 0) {
            String string = scan.nextLine();
            String[] arrsStrings = string.split(" ");
            if(arrsStrings[0].equals("IN")) {
                if(arrsStrings[2].equals("V")) {
                    //进队列
                    /*
                     * add与offer两者都是往队列尾部插入元素,不同的时候,当超出队列界限的时候,
                     * add()方法是抛出异常让你处理,而offer()方法是直接返回false
                     */
//                    vipQueue.add(arrsStrings[1]);
                    vipQueue.offer(arrsStrings[1]);
                }else {
                    nQueue.offer(arrsStrings[1]);
                }
            }else {
                if(arrsStrings[1].equals("V")) {
                    vipQueue.poll();
                }else {
                    nQueue.poll();
                }
            }
            M--;
        }
        for (String string : vipQueue) {
            System.out.println(string);
        }
        for (String string : nQueue) {
            System.out.println(string);
        }
        scan.close();
    }
}

二、CLZ的银行(循环队列)

问题描述

CLZ 银行只有两个接待窗口,VIP 窗口和普通窗口,VIP 用户进入 VIP 窗口排队,剩下的进入普通窗口排队。现有 M 次操作,操作有四种类型,如下:

  • IN name V:表示一名叫 name 的用户到 VIP 窗口排队
  • OUT V:表示 VIP 窗口队尾的用户离开排队
  • IN name N:表示一名叫 name 的用户到普通窗口排队
  • OUT N:表示普通窗口队尾的用户离开排队

求 M 次操作结束后 VIP 窗口队列和普通窗口队列中的姓名。

要求:使用循环队列实现该题

输入描述

第一行是一个整数 M(1≤M≤1000),表示一共有 M 次操作。

第二行到第 M+1 行输入操作,格式如下:

  • IN name V
  • OUT V
  • IN name N
  • OUT N

输出描述

输出 M 次操作后 VIP 窗口队列和普通窗口队列中的姓名(从头到尾),先输出 VIP 窗口队列后输出普通窗口队列。

运行限制

  • 最大运行时间:1s
  • 最大运行内存: 128M

输入输出示例

输入:
5
IN xiaoming N
IN Adel V
IN laozhao N
OUT N
IN CLZ V
输出:
Adel
CLZ
laozhao

代码示例

package E_lanqiao;

import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改

public class Main {
    // 创建两个数组构造队列
    static Integer MAXSIZE = 1000;
    static String[] viparrsStrings = new String[MAXSIZE];
    static int vipfrontInteger = 0;
    static int viprearInteger = 0;

    static String[] narrStrings = new String[MAXSIZE];
    static int nfrontInteger = 0;
    static int nrearInteger = 0;
    // 入队列
    static boolean inQueue(String name1, String types) {
        // 队列头指针在队尾指针的下一位位置上,说明满了
            if(types.equals("V")) {
                if((viprearInteger + 1)%MAXSIZE == vipfrontInteger) {
                    return false;
                }else {
                    viparrsStrings[viprearInteger] = name1;
                    viprearInteger = (viprearInteger + 1) % MAXSIZE;
                    return true;
                }
            }else {
                if((nrearInteger + 1)%MAXSIZE == nfrontInteger) {
                    return false;
                }else {
                    narrStrings[nrearInteger] = name1;
                    nrearInteger = (nrearInteger + 1) % MAXSIZE;
                    return true;
                }
            }
    }
    // 出队列
    private static boolean outQueue(String types) {
        //出队列前判断队列是否为空
        if(types.equals("V")) {
            if(viprearInteger == vipfrontInteger) {
                return false;
            }else {
                vipfrontInteger = (vipfrontInteger+1)%MAXSIZE;
                return true;
            }
        }else {
            if(nrearInteger == nfrontInteger) {
                return false;
            }else {
                nfrontInteger = (nfrontInteger+1)%MAXSIZE;
                return true;
            }
        }
    }
    // 获取函数
    private static String getHead(String types) {
        if(types.equals("V")) {
            // 队列空 则返回空格
            if(viprearInteger == vipfrontInteger) {
                return "";
            }else {
                return viparrsStrings[vipfrontInteger];
            }
        }else {
            if(nfrontInteger == nrearInteger) {
                return "";
            }else {
                return narrStrings[nfrontInteger];
            }
        }
    }
    //主函数
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        //在此输入您的代码...
        int M = scan.nextInt();// 个数
        scan.nextLine();// 吃掉换行符

        while(M > 0) {
            String string = scan.nextLine();
            String[] arrsStrings = string.split(" ");
            if(arrsStrings[0].equals("IN")) {
                inQueue(arrsStrings[1], arrsStrings[2]);
            }else {
                outQueue(arrsStrings[1]);
            }
            M--;
        }
        String string = getHead("V");
        while(outQueue("V")) {
            System.out.println(string);
            string = getHead("V");
        }
        string = getHead("N");
        while (string != null) {
            System.out.println(string);
            nfrontInteger++;
            string = getHead("N");
        }
        scan.close();
    }
}

👏小结

本章学习了java中有关队列的实现,在java中有可调用的api实现队列(import java.util.Queue;)(Queue q = new LinkedList();)(具体实现方法与细节后面介绍,可提前关注👆😁),在比赛中可无需花费大量的时间手撕队列,但学习的路上还是不能将其跳过,应面面俱到。冲冲冲!

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BXuan随笔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值