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

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

背包,队列

可以先看他们的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 = 3
	return (rear + maxSize - front) % maxSize;
}

显示队列的头数据

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/178248.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

从零开始学习typescript——什么是typescript

什么是typescript typescript是javascript 类型的超级&#xff0c;他可以编译成纯javascript. TypeScript可以在任何浏览器、任何计算机和任何操作系统上运行&#xff0c;并且是开源的。 这个是typescript 官网对 typescript的描述 背景及特点 TypeScript是微软开发的一个开源…

机器学习/sklearn 笔记:K-means,kmeans++

1 K-means介绍 1.0 方法介绍 KMeans算法通过尝试将样本分成n个方差相等的组来聚类&#xff0c;该算法要求指定群集的数量。它适用于大量样本&#xff0c;并已在许多不同领域的广泛应用领域中使用。KMeans算法将一组样本分成不相交的簇&#xff0c;每个簇由簇中样本的平均值描…

GIT实践与常用命令---回退

实践场景 场景1 回退提交 在日常工作中&#xff0c;我们可能会和多个同事在同一个分支进行开发&#xff0c;有时候我们可能会出现一些错误提交&#xff0c;这些错误提交如果想撤销&#xff0c;可以有两种解决办法:回退( reset )、反做(revert) keywords&#xff1a;reset、rev…

【计算方法与科学建模】矩阵特征值与特征向量的计算(二):Jacobi 过关法及其Python实现(Jacobi 旋转法的改进)

文章目录 一、Jacobi 旋转法1. 基本思想2. 注意事项 二、Jacobi 过关法1. 基本思想2. 注意事项 三、Python实现迭代过程&#xff08;调试&#xff09; 矩阵的特征值&#xff08;eigenvalue&#xff09;和特征向量&#xff08;eigenvector&#xff09;在很多应用中都具有重要的数…

Python 提高篇学习笔记(一):深拷贝和浅拷贝

文章目录 一、什么是对象的引用二、深拷贝和浅拷贝2.1 浅拷贝(Shallow Copy)2.2 深拷贝(Deep Copy)2.3 copy.copy和copy.deepcopy的区别 一、什么是对象的引用 在 Python 中&#xff0c;对象的引用是指变量指向内存中某个对象的地址或标识符。当你创建一个新的对象(比如一个整…

合格的全栈测试工程师,需要掌握哪些测试工具?

前言 俗话说&#xff0c;工欲善其事&#xff0c;必先利其器&#xff0c;所以一个好的软件测试工程师必须善于使用各种软件测试工具。软件测试工具是通过一些工具能够使软件的一些简单问题直观的展示在测试人员的面前&#xff0c;这样能使测试人员更好的找出软件错误的所在&…

iperf3 网络测试

iperf3 测试网络的上下行带宽 下载地址 https://iperf.fr/iperf-download.php 开启服务器 开启客户端 常用命令 -c 代表客户端-s 代表服务端-u 代表 udp-r 代表数据方向是否反向 https://baijiahao.baidu.com/s?id1731514357681464971&wfrspider&forpc

Python数据分析实战-爬取以某个关键词搜索的最新的500条新闻的标题和链接(附源码和实现效果)

实现功能 通过百度引擎&#xff0c;爬取以“开源之夏”为搜索关键词最新的500条新闻的标题和链接 实现代码 1.安装所需的库&#xff1a;你需要安装requests和beautifulsoup4库。可以使用以下命令通过pip安装&#xff1a; pip install requests beautifulsoup42.发起搜索请求…

Redis事务的理解与使用

文章目录 Redis 事务1)基本认识2)事务操作1.MULTI2.EXEC3.错误处理4.DISCARD5.WATCH6.SCRIPT Redis 事务 官方文档&#xff0c;永远是你学习的第一手资料&#xff1a;Redis 事务 1)基本认识 谈到事务&#xff0c;大家首先都会联想到 mysql 中复杂但又功能强大的“事务”&…

HTML新手入门笔记整理:HTML基本标签

结构标签 <html> </html> 告诉浏览器这个页面是从<html> 开始&#xff0c;到 </html>结束 <head> </head> 网页的头部&#xff0c;用于定义一些特殊内容&#xff0c;如页面标题、定时刷新、外部文件等。 <body> </body> …

Vue 3 渲染机制解密:从模板到页面的魔法

Vue 3 渲染机制解密 前言Vue 3的响应性系统1. **Reactivity API:**2. **Proxy 对象:**3. **Getter 和 Setter:**4. **依赖追踪:**5. **批量更新:**6. **异步更新:**7. **递归追踪:**8. **删除属性:** 虚拟DOM的角色1. **减少直接操作真实 DOM:**2. **高效的批量更新:**3. **跨平…

[论文笔记] Scaling Laws for Neural Language Models

概览: 一、总结 计算量、数据集大小、模型参数量大小的幂律 与 训练损失呈现 线性关系。 三个参数同时放大时,如何得到最佳的性能? 更大的模型 需要 更少的样本 就能达到相同的效果。 </

浅谈Python装饰器原理与用法分析

前言 本文实例讲述了Python装饰器原理与用法。分享给大家供大家参考&#xff0c;具体如下&#xff1a; 1、装饰器的本质是函数&#xff0c;主要用来装饰其他函数&#xff0c;也就是为其他函数添加附加功能 2、装饰器的原则: (1) 装饰器不能修改被装饰的函数的源代码 (2) 装…

智能卡接口芯片解决方案

一、基本概述 HCM8035是一款简洁且低成本的智能IC卡模拟接口芯片。内嵌升压模块&#xff0c;支持5V,3V,1.8V全电压读写。具有全面的安全保护机制&#xff0c;包括ESD保护&#xff0c;端口短路保护&#xff0c;电源上掉电保护。外围元件数目少&#xff0c;采用QFN32L封装。 今…

如何用惯性动作捕捉系统,快速创建数字人三维动画?

在动画制作领域&#xff0c;惯性动作捕捉技术已经逐渐成为一种重要的制作手段。通过动捕设备能够将动捕演员真实的动作转化为数字数据&#xff0c;然后在动画中再现这些动作。为了创造出逼真、流畅的数字人动画&#xff0c;惯性动作捕捉系统成为了一大工具。 根据采集方式的不…

感恩节的习俗 Custom of Family Dinner

感恩节是美国最普遍庆祝的传统节日之一。在每年11月的第四个星期四&#xff0c;感恩节如期而至。Thanksgiving is one of the most universally celebrated traditional American holidays. Every year, Thanksgiving arrives on the fourth Thursday of November without fail…

为Oracle链接服务器使用分布式事务

1 现象 在SQL Server中创建指向Oracle的链接服务器&#xff0c;SQL语句在事务中向链接服务器插入数据。返回链接服务器无法启动分布式事务的报错。 2 解决 在Windows平台下&#xff0c;SQL Server依赖分布式事务协调器&#xff08;MSDTC&#xff09;来使用分布式事务&#xff0…

光量子计算再创融资高峰!法国 Quandela获投5000万欧元

​&#xff08;图片来源&#xff1a;网络&#xff09; 法国光量子计算公司Quandela致力于开发首台光量子计算机&#xff0c;目前已获得超过5,000万欧元的巨额融资。投资者包括通过“法国2030计划”获得的法国政府支持以及银行合作伙伴、个人。新的投资者包括法国投资公司Seren…

Vue2系列 — 渲染函数 (render + createElement)

官网文档&#xff1a;https://v2.cn.vuejs.org/v2/guide/render-function.html 1 render 函数 render 函数 不使用模板&#xff0c;使用 js 生成虚拟 dom 2 createElement() 接受的参数&#xff1a; 参数1 节点类型参数2 attribute参数3 子节点 3 DEMO <template>&…

阿里云发送短信

官方代码如下&#xff1a; // This file is auto-generated, dont edit it. Thanks. package com.aliyun.sample;import com.aliyun.tea.*;public class Sample {/*** 使用AK&SK初始化账号Client* param accessKeyId* param accessKeySecret* return Client* throws Excep…