生活如果真能像队列一样的话

2023-11-23 01:12
文章标签 队列 生活 真能

本文主要是介绍生活如果真能像队列一样的话,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

生活如果真能像队列一样,那该多好啊。
——————————————————————————————————————————

背包,队列

可以先看他们的API:都含有一个无参构造函数,添加单个元素的方法,测试集合是否为空的方法和返回集合大小的方法。而Stack和Queue有能删除集合的特定元素的方法。

它们具有泛型迭代的特性。

泛型的使用,可以用它们存储任意类型的数据。
如:Stack , 用Item替换任意数据类型

Stack<String> stack = new Stack<String>();

而类型参数必须被实例化为引用类型。而java具有自动装箱和自动拆箱的机制,可以在引用类型和对应的原始数据类型之间转换。

Stack<Integer> stack = new Stack<Integer>();
stack.push(17);  //自动装箱 (int 转换为 Integer)
int i = stack.pop(); //自动拆箱 (Integer 转换为 int)

如果集合可迭代,可以使用如foreach循环来逐个访问集合中的元素,无需手动管理索引或遍历位置,这样可以简化代码实现。

Queue<String> queue = new LinkedList<>();
// 使用 foreach 循环来遍历 Queue
for (String element : queue) {System.out.println(element);
}

背包

特点:

  • 支持删除元素和遍历操作
  • 收集元素并迭代遍历所有收集到的元素
  • 迭代的顺序不确定(无序)且与用例无关
  • 主要用于统计计算,去重,求平均值或者样本标准差之类的场景

就理解成一个背包即可,里面各种球,一次放进去一个球,或者一次从里面找自己想要的具有某种特点的球。

Bag<Double> numbers = new Bag<Double>();
while (!StdIn.isEpty()) numbers.add(StdIn.readDouble());
int N = number.size(); // 背包的元素数量double sum = 0.0
for (double x : number)sum += x;
double mean = sum/N;sum = 0.0;
for(double x : number)sum += (x - mean)*(x- mean);
double std = Math.sqrt(sum/(N-1));

队列(queue)

先进先出队列是一种基于先进先出(FIFO) 策略的集合类型。

使用场景很常见,尤其是排队,打印机等待打印或者是计算机某些软件等待处理的任务。

因为是服务性的策略,所以主打一个公平,先到先得,等的越久越先服务。

Queue<Integer> queue = new Queue<Integer>();
// Enqueue 操作  可以通过add()或offer()方法实现
queue.add("A");
queue.add("B");
queue.offer("C");// dequeue:从队列的头部移除并返回一个元素,可以使用remove()或poll()方法来实现
String dequeuedElement = queue.remove();
System.out.println("Dequeued element: " + dequeuedElement);

队列是一个有序列表,可以用数组或是链表来实现。

数组模拟队列思路

  • 队列本身是有序列表,若使用数组的结构来存储队列的数据,则队列数组的声明如下图, 其中 maxSize 是该队 列的最大容量。
  • 因为队列的输出、输入是分别从前后端来处理,因此需要两个变量 front 及 rear 分别记录队列前后端的下标, front 会随着数据输出而改变,而 rear 则是随着数据输入而改变,如图所示:

在这里插入图片描述

准备工作思路:

  1. 将front和rear初始化为-1 , 为了表示队列为空的状态 (当队列中添加第一个元素时,front和rear都会更新为0,表示队列中有一个元素)

  2. 当 front == rear 则代表队列为空

  3. 当 rear == maxSize - 1 则代表队列为满

class ArrayQueue {
private int maxSize; // 表示数组的最大容量
private int front; // 队列头
private int rear; // 队列尾
private int[] arr; // 该数据用于存放数据, 模拟队列// 创建队列的构造器
public ArrayQueue(int arrMaxSize) {maxSize = arrMaxSize;arr = new int[maxSize];front = -1; // 指向队列头部,分析出 front 是指向队列头的前一个位置.rear = -1; // 指向队列尾,指向队列尾的数据(即就是队列最后一个数据)
}// 判断队列是否满   (队列尾指向数组的最大索引)
public boolean isFull() {return rear == maxSize - 1;
}// 判断队列是否为空   (初始时,两指针都为-1,指向同一个位置)
public boolean isEmpty() {return rear == front;
}

存入数据思路分析

1.添加元素时,判断队列是不是满的。若不是,则头指针不动,用于元素出队列,将尾指针后移:rear+1

2.再将数据存入 rear 所指的数组元素中

// 添加数据到队列
public void addQueue(int n) {
// 判断队列是否满if (isFull()) {System.out.println("队列满,不能加入数据~");return;}rear++; // 让 rear 后移arr[rear] = n;
}

出队列(获取队列的数据)代码

public int getQueue() {
// 判断队列是否空if (isEmpty()) {// 通过抛出异常throw new RuntimeException("队列空,不能取数据");}front++; // front 后移 满足先进先出原则。return arr[front];
}

显示队列中的所有数据 代码:

public void showQueue() {// 遍历if (isEmpty()) {System.out.println("队列空的,没有数据~~");return;}for (int i = 0; i < arr.length; i++) {System.out.printf("arr[%d]=%d\n", i, arr[i]);}
}

显示队列的头数据 代码:

public int headQueue() {if (isEmpty()) {throw new RuntimeException("队列空的,没有数据~~");}return arr[front + 1];}
}

对于这个代码所模拟的队列进行问题分析及方案优化:

  • 问题:目前数组使用一次就不能用,没有出队列的功能,则没有达到复用的效果。且如果队列尾部的空间已满,而队列头部仍有空间,此时无法再添加元素
  • 优化方案:将这个数组使用算法,改进成一个环形的队列 通过取模(%)变成循环

数组模拟环形队列

​ 对前面的数组模拟队列进行优化,实现可以复用。成为是一个环形的循环队列。(通过取模的方式来实现即可)

分析说明:

  1. 因为是环形结构,满了会回头。所以当尾索引的下一个为头索引时,表示队列满了。因此将队列容量空出一个作为约定。通过这个约定可以得出, (rear + 1) % maxSize == front,代表队列满了。

  2. rear == front 则代表队列为空

    当你定义了1个长度为5的队列,已经有了4个元素。这个时候头指针指着第一个数字,尾指针值向

    具体思路如下:

    1. 将front指向队列的第一个元素,即front=0

    2. 将rear指向队列最后一个元素的后一个位置,即rear=0。(这里需要注意,rear指向的位置实际上是不存储数据的,只是为了区分队列空和满的情况,因此需要浪费一个位置

      在这里插入图片描述

        这里比如当你定义了1个长度为5的队列,已经有了4个元素。这个时候头指针指着第一个元素,尾指针值向第4个元素后面的位置。这时候你再加一个元素的话,那尾指针就指回了第一个位置,这样子就出现了rear == front。那你就没办法确定到底是队列满了还是队列空了。因此采用(rear + 1) % maxSize == front就表示队列满了,此时rear指向的位置实际上是不存储数据的。
      
      • 在网上找到的其他思路:新增一个容量 capacity 字段,并进行维护,当 capacity=size 表示队列已满。维护一个标记,或者当 头指针=尾指针 时同步判断当前位置是否有元素来判断当前是队空还是队满。
        
      • 	现在使用的方法会浪费一个空间;而新增容量字段需要维护,而标记的方法队列空和队列满的时候需要判断是那种情况,影响性能。一般使用浪费一个空间的方法,用空间换时间。
        
    3. 在判断队列是否时,尾指针的下一个位置会等于头指针的位置。所以使用**(rear + 1) % maxSize == front**条件,当rear和front相邻且都指向有数据的位置时,队列为满。

      public boolean isFull() {return (rear + 1) % maxSize == front;
      }
    4. 在判断队列是否为时,使用rear == front的条件,当队列中没有元素时,front和rear都指向同一个位置。

      public boolean isEmpty() {return rear == front;
      }
      
    5. 计算队列中有效数据元素的个数时,使用**(rear + maxSize - front) % maxSize**的公式,由于队列是循环的,所以队列的尾部可能在数组的起始位置之前。

      计算出队列尾指针rear到队列头指针front的距离,并进行模运算,得到实际的元素个数。

添加数据到队列

public void addQueue(int n) {// 判断队列是否满if (isFull()) {System.out.println("队列满,不能加入数据~");return;}//直接将数据加入arr[rear] = n;//将 rear 后移, 这里必须考虑取模!rear = (rear + 1) % maxSize;
}

获取队列的数据, 出队列

public int getQueue() {// 判断队列是否空if (isEmpty()) {// 通过抛出异常throw new RuntimeException("队列空,不能取数据");}// 这里需要分析出 front 是指向队列的第一个元素// 1. 先把 front 对应的值保留到一个临时变量// 2. 然后将 front 后移, 考虑取模!// 3. 将临时保存的变量返回int value = arr[front];front = (front + 1) % maxSize;  return value;
}

显示队列的所有数据

public void showQueue() {// 遍历if (isEmpty()) {System.out.println("队列空的,没有数据~~");return;}for (int i = front; i < front + size() ; i++) {// 使用 i % maxSize 的目的是确保索引值在循环队列的有效范围内
//假设队列的最大大小为 5,且队列起始位置front是2,不取模的话,那就超出了队列范围,应该回到队列的开头,则需要取模。System.out.printf("arr[%d]=%d\n", i % maxSize, arr[i % maxSize])}
}// 求出当前队列有效数据的个数
public int size() {// rear = 2// front = 1// maxSize = 3return (rear + maxSize - front) % maxSize;
}

显示队列的头数据

public int headQueue() {// 判断if (isEmpty()) {throw new RuntimeException("队列空的,没有数据~~");}return arr[front];}
}

————————————————————————————————————
那这样子是不是就有机会了

这篇关于生活如果真能像队列一样的话的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/414263

相关文章

如何通过Python实现一个消息队列

《如何通过Python实现一个消息队列》这篇文章主要为大家详细介绍了如何通过Python实现一个简单的消息队列,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录如何通过 python 实现消息队列如何把 http 请求放在队列中执行1. 使用 queue.Queue 和 reque

解读Redis秒杀优化方案(阻塞队列+基于Stream流的消息队列)

《解读Redis秒杀优化方案(阻塞队列+基于Stream流的消息队列)》该文章介绍了使用Redis的阻塞队列和Stream流的消息队列来优化秒杀系统的方案,通过将秒杀流程拆分为两条流水线,使用Redi... 目录Redis秒杀优化方案(阻塞队列+Stream流的消息队列)什么是消息队列?消费者组的工作方式每

Redis延迟队列的实现示例

《Redis延迟队列的实现示例》Redis延迟队列是一种使用Redis实现的消息队列,本文主要介绍了Redis延迟队列的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习... 目录一、什么是 Redis 延迟队列二、实现原理三、Java 代码示例四、注意事项五、使用 Redi

hdu1180(广搜+优先队列)

此题要求最少到达目标点T的最短时间,所以我选择了广度优先搜索,并且要用到优先队列。 另外此题注意点较多,比如说可以在某个点停留,我wa了好多两次,就是因为忽略了这一点,然后参考了大神的思想,然后经过反复修改才AC的 这是我的代码 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<

poj 3190 优先队列+贪心

题意: 有n头牛,分别给他们挤奶的时间。 然后每头牛挤奶的时候都要在一个stall里面,并且每个stall每次只能占用一头牛。 问最少需要多少个stall,并输出每头牛所在的stall。 e.g 样例: INPUT: 51 102 43 65 84 7 OUTPUT: 412324 HINT: Explanation of the s

poj 2431 poj 3253 优先队列的运用

poj 2431: 题意: 一条路起点为0, 终点为l。 卡车初始时在0点,并且有p升油,假设油箱无限大。 给n个加油站,每个加油站距离终点 l 距离为 x[i],可以加的油量为fuel[i]。 问最少加几次油可以到达终点,若不能到达,输出-1。 解析: 《挑战程序设计竞赛》: “在卡车开往终点的途中,只有在加油站才可以加油。但是,如果认为“在到达加油站i时,就获得了一

poj3750约瑟夫环,循环队列

Description 有N个小孩围成一圈,给他们从1开始依次编号,现指定从第W个开始报数,报到第S个时,该小孩出列,然后从下一个小孩开始报数,仍是报到S个出列,如此重复下去,直到所有的小孩都出列(总人数不足S个时将循环报数),求小孩出列的顺序。 Input 第一行输入小孩的人数N(N<=64) 接下来每行输入一个小孩的名字(人名不超过15个字符) 最后一行输入W,S (W < N),用

POJ2010 贪心优先队列

c头牛,需要选n头(奇数);学校总共有f的资金, 每头牛分数score和学费cost,问合法招生方案中,中间分数(即排名第(n+1)/2)最高的是多少。 n头牛按照先score后cost从小到大排序; 枚举中间score的牛,  预处理左边与右边的最小花费和。 预处理直接优先队列贪心 public class Main {public static voi

Java并发编程之——BlockingQueue(队列)

一、什么是BlockingQueue BlockingQueue即阻塞队列,从阻塞这个词可以看出,在某些情况下对阻塞队列的访问可能会造成阻塞。被阻塞的情况主要有如下两种: 1. 当队列满了的时候进行入队列操作2. 当队列空了的时候进行出队列操作123 因此,当一个线程试图对一个已经满了的队列进行入队列操作时,它将会被阻塞,除非有另一个线程做了出队列操作;同样,当一个线程试图对一个空

FreeRTOS学习笔记(六)队列

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、队列的基本内容1.1 队列的引入1.2 FreeRTOS 队列的功能与作用1.3 队列的结构体1.4 队列的使用流程 二、相关API详解2.1 xQueueCreate2.2 xQueueSend2.3 xQueueReceive2.4 xQueueSendFromISR2.5 xQueueRecei