数据结构之队列(queue)
队列介绍
1.队列是一个有序列表,可以用数组或是链表来实现。
2.遵循先入先出的原则。即:先存入队列的数据,要先取出。后存入的要后取出。
应用场景
比如某某银行叫号系统:
数组模拟队列
队列本身是有序列表,若使用数组的结构来存储队列的数据,则队列数组的声明如下图, 其中 maxSize 是该队列的最大容量。
因为队列的输出、输入是分别从前后端来处理,因此需要两个变量 front及 rear分别记录队列前后端的下标,front 会随着数据输出而改变,而 rear则是随着数据输入而改变
示意图:(使用数组模拟队列示意图)
当我们将数据存入队列时称为”addQueue”,addQueue 的处理需要有两个步骤:思路分析
1.将尾指针往后移:rear+1 , 当front == rear 【空】
2.若尾指针 rear 小于队列的最大下标 maxSize-1,则将数据存入 rear所指的数组元素中,否则无法存入数据。 rear == maxSize - 1[队列满]
代码实现:
- package com.queueArray;
- import java.util.Scanner;
- /**
- * Created by wanbf on 2019/6/1. 队列
- */
- public class QueueAarray {
- public static void main(String[] args) {
- //测试一把
- //创建一个队列
- ArrayQueue queue = new ArrayQueue(3);
- char key = ' '; //接收用户输入
- Scanner scanner = new Scanner(System.in);//
- boolean loop = true;
- //输出一个菜单
- while(loop) {
- System.out.println("s(show): 显示队列");
- System.out.println("e(exit): 退出程序");
- System.out.println("a(add): 添加数据到队列");
- System.out.println("g(get): 从队列取出数据");
- System.out.println("h(head): 查看队列头的数据");
- key = scanner.next().charAt(0);//接收一个字符
- switch (key) {
- case 's':
- queue.showQueue();
- break;
- case 'a':
- System.out.println("输出一个数");
- int value = scanner.nextInt();
- queue.addQueue(value);
- break;
- case 'g': //取出数据
- try {
- int res = queue.getQueue();
- System.out.printf("取出的数据是%d\n", res);
- } catch (Exception e) {
- // TODO: handle exception
- System.out.println(e.getMessage());
- }
- break;
- case 'h': //查看队列头的数据
- try {
- int res = queue.headQueue();
- System.out.printf("队列头的数据是%d\n", res);
- } catch (Exception e) {
- // TODO: handle exception
- System.out.println(e.getMessage());
- }
- break;
- case 'e': //退出
- scanner.close();
- loop = false;
- break;
- default:
- break;
- }
- }
- System.out.println("程序退出~~");
- }
- }
- // 使用数组模拟队列-编写一个ArrayQueue类
- 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;
- }
- // 判断队列是否为空
- public boolean isEmpty() {
- return rear == front;
- }
- // 添加数据到队列
- 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.目前数组使用一次就不能使用了,没有达到复用的效果。
2.将这个数组使用算法,改进成一个环形的队列,取模:%
数组模拟环形队列
对前面的数组模拟队列的优化,充分利用数组
因此将数组看做是一个环形的。(通过取模的方式来实现即可)
分析说明:
1.尾索引的下一个为头索引时表示队列满,即将队列容量空出一个作为约定,这个在做判断队列满的时候需要注意 (rear + 1) % maxSize == front 满]
2.rear == front [空]
3.测试示意图:
代码实现:
- package com.queueArray;
- import java.util.Scanner;
- /**
- * Created by wanbf on 2019/6/1. 环形队列
- */
- public class CircleQueueArray {
- public static void main(String[] args) {
- //测试一把
- System.out.println("测试数组模拟环形队列的案例~~~");
- // 创建一个环形队列
- CircleArray queue = new CircleArray(4); //说明设置4, 其队列的有效数据最大是3
- char key = ' '; // 接收用户输入
- Scanner scanner = new Scanner(System.in);//
- boolean loop = true;
- // 输出一个菜单
- while (loop) {
- System.out.println("s(show): 显示队列");
- System.out.println("e(exit): 退出程序");
- System.out.println("a(add): 添加数据到队列");
- System.out.println("g(get): 从队列取出数据");
- System.out.println("h(head): 查看队列头的数据");
- key = scanner.next().charAt(0);// 接收一个字符
- switch (key) {
- case 's':
- queue.showQueue();
- break;
- case 'a':
- System.out.println("输出一个数");
- int value = scanner.nextInt();
- queue.addQueue(value);
- break;
- case 'g': // 取出数据
- try {
- int res = queue.getQueue();
- System.out.printf("取出的数据是%d\n", res);
- } catch (Exception e) {
- // TODO: handle exception
- System.out.println(e.getMessage());
- }
- break;
- case 'h': // 查看队列头的数据
- try {
- int res = queue.headQueue();
- System.out.printf("队列头的数据是%d\n", res);
- } catch (Exception e) {
- // TODO: handle exception
- System.out.println(e.getMessage());
- }
- break;
- case 'e': // 退出
- scanner.close();
- loop = false;
- break;
- default:
- break;
- }
- }
- System.out.println("程序退出~~");
- }
- }
- class CircleArray {
- private int maxSize; // 表示数组的最大容量
- //front 变量的含义做一个调整: front 就指向队列的第一个元素, 也就是说 arr[front] 就是队列的第一个元素
- //front 的初始值 = 0
- private int front;
- //rear 变量的含义做一个调整:rear 指向队列的最后一个元素的后一个位置. 因为希望空出一个空间做为约定.
- //rear 的初始值 = 0
- private int rear; // 队列尾
- private int[] arr; // 该数据用于存放数据, 模拟队列
- public CircleArray(int arrMaxSize) {
- maxSize = arrMaxSize;
- arr = new int[maxSize];
- }
- // 判断队列是否满
- public boolean isFull() {
- return (rear + 1) % maxSize == front;
- }
- // 判断队列是否为空
- public boolean isEmpty() {
- return 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;
- }
- // 思路:从front开始遍历,遍历多少个元素
- // 动脑筋
- for (int i = front; i < front + size() ; i++) {
- 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];
- }
- }
代码
数据结构之队列(queue)的更多相关文章
- Python与数据结构[2] -> 队列/Queue[0] -> 数组队列的 Python 实现
队列 / Queue 数组队列 数组队列是队列基于数组的一种实现,其实现类似于数组栈,是一种FIFO的线性数据结构. Queue: <--| 1 | 2 | 3 | 4 | 5 |<-- ...
- 数据结构:队列queue 函数push() pop size empty front back
队列queue: push() pop() size() empty() front() back() push() 队列中由于是先进先出,push即在队尾插入一个元素,如:可以输出:Hello W ...
- 算法与数据结构基础 - 队列(Queue)
队列基础 队列具有“先进先出”的特点,用这个特点我们可以用它来处理时间序列相关或先后次序相关的问题,例如 LeetCode题目 933. Number of Recent Calls,时间复杂度O(1 ...
- 【Java数据结构学习笔记之二】Java数据结构与算法之队列(Queue)实现
本篇是数据结构与算法的第三篇,本篇我们将来了解一下知识点: 队列的抽象数据类型 顺序队列的设计与实现 链式队列的设计与实现 队列应用的简单举例 优先队列的设置与实现双链表实现 队列的抽象数据类型 ...
- 【Java数据结构学习笔记之三】Java数据结构与算法之队列(Queue)实现
本篇是数据结构与算法的第三篇,本篇我们将来了解一下知识点: 队列的抽象数据类型 顺序队列的设计与实现 链式队列的设计与实现 队列应用的简单举例 优先队列的设置与实现双链表实现 队列的抽象数据类型 ...
- 数据结构——链队列(linked queue)
/* linkedQueue.c */ /* 链队列 */ #include <stdio.h> #include <stdlib.h> #include <stdboo ...
- python基本数据结构栈stack和队列queue
1,栈,后进先出,多用于反转 Python里面实现栈,就是把list包装成一个类,再添加一些方法作为栈的基本操作. 栈的实现: class Stack(object): #初始化栈为空列表 def _ ...
- Java多线程总结之线程安全队列Queue
在Java多线程应用中,队列的使用率很高,多数生产消费模型的首选数据结构就是队列.Java提供的线程安全的Queue可以分为阻塞队列和非阻塞队列,其中阻塞队列的典型例子是BlockingQueue,非 ...
- Java中的队列Queue,优先级队列PriorityQueue
队列Queue 在java5中新增加了java.util.Queue接口,用以支持队列的常见操作.该接口扩展了java.util.Collection接口. Queue使用时要尽量避免Collecti ...
随机推荐
- AndoridSQLite数据库开发基础教程(4)
AndoridSQLite数据库开发基础教程(4) 安装SQLiteManager 以下是SQLiteManager的安装步骤: (1)双击下载的.exe文件,弹出SQLiteManager Setu ...
- leetcode 576. Out of Boundary Paths 、688. Knight Probability in Chessboard
576. Out of Boundary Paths 给你一个棋盘,并放一个东西在一个起始位置,上.下.左.右移动,移动n次,一共有多少种可能移出这个棋盘 https://www.cnblogs.co ...
- Docs-.NET-C#-指南-语言参考-关键字-值类型:可以 null 的值类型
ylbtech-Docs-.NET-C#-指南-语言参考-关键字-值类型:可以 null 的值类型 1.返回顶部 1. Nullable value types (C# reference) 2019 ...
- Vuex 的使用 State Mutation Getter Action
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex); /*1.state在vuex中用于存储数据*/ var state={ cou ...
- 【Mybatis】MyBatis之整合Spring(八)
创建环境 系统:macOS Java:1.8 软件:eclipse,maven,mysql 创建步骤 本例:创建一个Maven项目(SpringMVC+Spring+Mybatis),页面上展示员工列 ...
- 转:HR schema
###createe RemRem $Header: hr_cre.sql 29-aug-2002.11:44:03 hyeh Exp $RemRem hr_cre.sqlRemRem Copyrig ...
- Linux系统调优——系统整体运行状态排查(七)
(1).vmstat vmstat命令是最常见的Linux/Unix监控工具,可以展现给定时间间隔的服务器的整体状态值,包括服务器的CPU使用率,MEM内存使用,VMSwap虚拟内存交换情况,IO读写 ...
- 123457123456#5#----com.MC.HuaHuaGame866----前拼后广--babyDrawGame-mc555
com.MC.HuaHuaGame866----前拼后广--babyDrawGame-mc
- kafka删除topic后再创建同名的topic报错(ERROR org.apache.kafka.common.errors.TopicExistsException)
[hadoop@datanode3 logs]$ kafka-topics.sh --delete --zookeeper datanode1:2181 --topic firstTopic firs ...
- MySQL插入大批量数据时报错“The total number of locks exceeds the lock table size”的解决办法
事情的原因是:我执行了一个load into语句的SQL将一个很大的文件导入到我的MySQL数据库中,执行了一段时间后报错"The total number of locks exceeds ...