java 数据结构_Java版-数据结构-队列(数组队列)
前言
看过笔者前两篇介绍的 Java版
数据结构 数组
和 栈
的盆友,都给予了笔者一致的好评,在这里笔者感谢大家的认可!!!
由于本章介绍的数据结构是 队列
,在队列的实现上会基于前面写的 动态数组
来实现,而 队列
又和 栈
不论是从特点上和操作上都有类似之处,所以在这里对这两种数据结构不了解的朋友,可以去看一下笔者前两篇文章介绍的数据结构 数组
和 栈
,这里笔者把链接贴出来(看过的盆友可以跳过此步骤...)
- Java版-数据结构-数组
- Java版-数据结构-栈
介绍
队列是一种特殊的线性表,它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。
队列的操作方式和 栈
类似,唯一的区别在于队列只允许新数据在后端(rear)进行添加。
特点
- 队列是一种线性结构
- 只能从一端(队尾)添加元素,从另一端(队首)取出元素
- 先进先出,First In First Out(FIFO)
之前在介绍栈的时候,通过示意图来帮助大家了解什么是栈;这里,我仍采用示意图形式向大家演示队列常用的两个操作: 入队操作
和 出队操作
。
队列入队操作
这里我们可以形象地想成我们到银行办理业务排队的场景,现在A、B、C三个元素分别到银行柜台排成一条队办理业务(我们都是文明的孩纸,总不能插队O(∩_∩)O哈!),依次排队的元素是:A、B、C。
队列出队操作
当元素 A
办理完业务时,当前是元素 A
先离开队列,然后是元素 B
,最后是元素 C
我们时刻要牢记队列,入队是从
队尾
一端进行入队,出队是从队首
一端进行出队,是一种:先进先出的数据结构。
本文会介绍队列的两张实现方式,一种是数组队列,另外一种是循环队列,考虑篇幅长度原因,本篇我们暂时只介绍数组队列,循环队列放在下一篇介绍。
数组队列(底层基于数组实现)
底层原理分析
现在我们声明一个数组的长度(capacity=3),元素个数为(size=0)的int类型数组的空队列,在这里,假设对队列的 队首
为数组的 左侧
, 队尾
为数组的 右侧
,示意图如下:
现在如果我们有四个元素:A、B、C、D要入队
元素 A
入队
元素 A
已经入队了,现在开始元素 B
入队
元素 A
和元素 B
已经入队了,现在开始元素 C
入队
元素 A
、 B
和 C
已经分别入队了,现在如果我们要开始元素 D
入队,根据我们之前定义的动态数组的特性,如果元素 D
进行入队操作,会发现此时我们的数组已经满了,这时候数组会自动地 扩容
(扩容的原理:新建一个容量是原数组容量两倍的数组,把原数组中的元素依次拷贝到新的数组中,最后引用指向新的数组)的原来的两倍(具体扩容多少,盆友可以自行设置)示意图如下:
到这里我们已经完成了元素:A、B、C、D的入队操作了,现在我们来看一下,它们的出队操作,根据队列的特性,队列是一种 先进先出
的数据结构,之前入队操作顺序依次是: A->B->C->D
,那么出队操作顺序仍然是: A->B->C->D
现在我们来看一下元素 A
和元素 B
出队后的示意图:
元素 C
和 D
的出队原理和元素 A
出队的原理一样,直至全部出队完成,变成空队列
在元素出队的过程中,相应地也会进行缩容操作,之前笔者这边定义,当数组中元素的个数(size)等于数组容量(capacity)的一半时,数组会进行缩容操作,这也正是动态数组的特点。
了解了数组队列的底层原理之后,接下来我们用代码来实现一下(建议盆友,在看之前,自己可以尝试写一下,然后在看,这样印象可能会比较深刻O(∩_∩)O哈!)
队列基本操作
- 向队列中添加元素(入队)
void enqueue(E e);
- 从队列中取出元素(出队)
E dequeue();
- 获取队首元素
E getFront();
- 获取队列中元素个数
int getSize();
- 判断队列是否为空
boolean isEmpty();
代码实现
接口定义 :Queue
public interface Queue<E> {/*** 入队** @param e*/void enqueue(E e);/*** 出队** @return*/E dequeue();/*** 获取队首元素** @return*/E getFront();/*** 获取队列中元素的个数** @return*/int getSize();/*** 判断队列是否为空** @return*/boolean isEmpty();
}
DynamicArrayQueue 类实现接口 Queue
public class DynamicArrayQueue<E> implements Queue<E> {/*** 用数组存放队列中元素的个数*/private DynamicArray<E> dynamicArray;/*** 指定容量,初始化队列** @param capacity*/public DynamicArrayQueue(int capacity) {dynamicArray = new DynamicArray<>(capacity);}/*** 默认容量,初始化队列*/public DynamicArrayQueue() {dynamicArray = new DynamicArray<>();}@Overridepublic void enqueue(E e) {dynamicArray.addLast(e);}@Overridepublic E dequeue() {return dynamicArray.removeFirst();}@Overridepublic E getFront() {return dynamicArray.getFirst();}@Overridepublic int getSize() {return dynamicArray.getSize();}@Overridepublic boolean isEmpty() {return dynamicArray.isEmpty();}@Overridepublic String toString() {return "DynamicArrayQueue{" +"【队首】dynamicArray=" + dynamicArray + "}【队尾】";}
}
测试类: DynamicArrayQueueTest
public class DynamicArrayQueueTest {@Testpublic void testArrayQueue() {// 指定容量(capacity=6)初始化队列DynamicArrayQueue<String> dynamicArrayQueue = new DynamicArrayQueue(3);System.out.println("初始队列:" + dynamicArrayQueue);// 准备入队元素List<String> enQueueElements = Arrays.asList("A", "B", "C");// 元素入队enQueueElements.forEach(x -> dynamicArrayQueue.enqueue(x));System.out.println("元素A、B、C入队:" + dynamicArrayQueue);// 此时如果又有一个元素D入队,会发生扩容操作 (size == capacity)进行扩容dynamicArrayQueue.enqueue("D");System.out.println("元素D入队,发生扩容:" + dynamicArrayQueue);// 元素A出队,会发生缩容操作(size == capacity / 2)进行缩容dynamicArrayQueue.dequeue();System.out.println("元素A出队,发生缩容:" + dynamicArrayQueue);// 元素B出队dynamicArrayQueue.dequeue();System.out.println("元素B出队:" + dynamicArrayQueue);}
}
运行结果
初始队列:DynamicArrayQueue{【队首】dynamicArray=DynamicArray{data=[null, null, null], size=0,capacity=3}}【队尾】元素A、B、C入队:DynamicArrayQueue{【队首】dynamicArray=DynamicArray{data=[A, B, C], size=3,capacity=3}}【队尾】元素D入队,发生扩容:DynamicArrayQueue{【队首】dynamicArray=DynamicArray{data=[A, B, C, D, null, null], size=4,capacity=6}}【队尾】元素A出队,发生缩容:DynamicArrayQueue{【队首】dynamicArray=DynamicArray{data=[B, C, D], size=3,capacity=3}}【队尾】元素B出队:DynamicArrayQueue{【队首】dynamicArray=DynamicArray{data=[C, D, null], size=2,capacity=3}}【队尾】
细心的盆友,会发现,因为队列的底层是数组来实现的,队列的出队操作实际上就是:删除数组中的第一个元素,后面的所有元素都要往前面挪一位;其实这样性能是比较低下的,时间复杂度是O(n)级别的。
我们想如果元素进行出队操作后,能否不挪动后面的元素,还能维持队列的特性,这样问题不就解决了吗?盆友可以自行思考一下。
完整版代码GitHub仓库地址:Java版数据结构-队列(数组队列) 欢迎大家【关注】和【Star】
本篇完成的数组队列是基于之前【Java版-数据结构-数组】动态数组来实现的,下一篇笔者会给大家介绍用循环队列来解决数组队列带来的性能问题。接下来,笔者还会一一的实现其它常见的数组结构。
- 静态数组
- 动态数组
- 栈
- 数组队列
- 循环队列
- 链表
- 循环链表
- 二分搜索树
- 优先队列
- 堆
- 线段树
- 字典树
- AVL
- 红黑树
- 哈希表
- ....
持续更新中,欢迎大家关注公众号:小白程序之路(whiteontheroad),第一时间获取最新信息!!!
java 数据结构_Java版-数据结构-队列(数组队列)相关推荐
- 数据结构-队列-数组队列
自定义队列 文章目录 自定义队列 数组队列 简述: 数组环形队列 数组队列 简述: 队列本身是有序列表,若使用数组的结构来存储队列的数据,则队列数组的声明如下图, 其中 maxSize 是该队列的最大 ...
- java循环队列_Java版-数据结构-队列(循环队列)
前情回顾 在上一篇,笔者给大家介绍了数组队列,并且在文末提出了数组队列实现上的劣势,以及带来的性能问题(因为数组队列,在出队的时候,我们往往要将数组中的元素往前挪动一个位置,这个动作的时间复杂度O(n ...
- 数据结构Python版(四)——队列
目录 一.队列简介 二.顺序队列 2.1 非循环队列 2.2 循环队列 2.2.1 假溢出 2.2.2 循环队列的架构 2.2.3 循环队列的实现 三.链队 3.1 链队的完整实现 四.双端队列 4. ...
- java object 数组_Java用Object实现数组队列的泛思与理解
1.数组队列:能够限定只存一种数据或(不限定数据类型)同时存储多种数据的一个数组封装类 2.实现:使用泛型,创建对象时若指定数据类型,则只能存储一种数据,否则可以存储多种数据: 2.1.前者:类似于C ...
- 无锁队列java实现_java轻松实现无锁队列
深入解析java java虚拟机jvm编译器 348.5元 (需用券) 去购买 > 1.什么是无锁(Lock-Free)编程 当谈及 Lock-Free 编程时,我们常将其概念与 Mutex(互 ...
- java算法 例 百度云_Java版数据结构与算法(20集版)视频教程百度云下载
课程目录: 1 Y) C+ M. ~9 S' r7 i J# _数据结构-Java版(20集)7 {2 h5 w' i9 C' }& }$ J |____第20讲 - 图的最小生成树.avi ...
- java中数据结构_JAVA中数据结构总结
本篇文章主要总结一下JAVA中实现的几种数据结构 简述: List>:链表结构. Queue>:队列,只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,队列 ...
- java线性数据结构_Java实现数据结构之线性结构
一.顺序表 顺序表本质是使用数组储存数组的一种数据结构,在计算机的储存中是连续的分配内存的. 下面是我自己使用java实现的简单顺序表结构 package list; public class ...
- JAVA实现单链表数据结构_java实现数据结构单链表示例(java单链表)
/** * 单向链表 * */ public class nodelist { private static class node { // 节点类 e data; // 节点上的数据 node ne ...
最新文章
- Python运算符与Pandas方法的映射关系
- 20172311《程序设计与数据结构》第八周学习总结
- 设计模式原则总结--读《大话设计模式》有感 转
- Spring+Redis整合
- flink的savepoint实验-scala
- 3-8 基于SpringBoot连接数据库与配置MyBatis实操 创建表sql
- Linux的基本使用
- Windows Mobile和Wince(Windows Embedded CE )下使用.NET Compact Framework下注册表导出工具的开发...
- ImageLoader的简单分析(终结篇)
- shiro+springmvc+mybatis【转】
- 连续亏损的哈啰,转型多元化困难重重
- 链路聚合实现冗余功能综合实验
- 使用VGA实现移动方块
- 范莎学院计算机专业,范莎学院会不会不容易毕业?
- 德莱联盟 计算几何 线段相交
- 若依开发文档手册[持续更新:拥抱初次使用若依的开发者]
- 41-C++自动存储、静态存储和动态存储
- R语言survival包的survfit函数拟合生存曲线数据、survminer包的ggsurvplot函数可视化生存曲线、绘制分面生存曲线(facet_grid)
- 基础才是王道——TCP/IP详解学习笔记 这位仁兄写得太好了
- U盘产品如何做好软文推广利用软文来打造为产品引流宣传
热门文章
- 白话解说:阻塞和非阻塞,同步和异步
- R-apply()函数
- Mac 10.12彻底关闭Dashboard
- 【Python】 配置解析ConfigParser 命令行参数解析optparser
- 工作日志WebRoot--编辑页关于处理两个关联的选择框
- Spring学习(24)--- AOP之 Aspect instantiation models(aspect实例模式)特别说明
- 第 3 章 镜像 - 018 - 镜像命名的最佳实践
- 4.10/4.11/4.12 lvm讲解 4.13 磁盘故障小案例
- python3基础3--数据类型--数据运算--表达式if -else-while-for
- WPF01(xaml)