数据结构(3):队列的原理和实现
完整代码拉到最底下
一、介绍
队列顾名思义就像我们生活中排队一样,先进先出。
如上图所示,25、16、5、9依次在队列中,按照顺序拿出的数据也分别是25、26、5、9。
二、实现过程及思路
底层使用数组来实现,实现的功能有插入数据到队尾、移除队首数据、查看队首数据、判断队列是否为空、判断队列是否存满。
将队列的元素存储在数组的某个区间内,队列在数组中是连续的,所以使用变量标记队列在数组中的位置。
1、编写类及属性
我们可以使用elements变量标记队列中元素的数量,使用front变量标记队首元素在数组的索引,end变量标记队尾元素在数组中的索引。
public class MyQueue { private Object[] arr;//存放队列元素的数组 private int elements;//队列元素数量 private int front;//队头元素在数组中的索引 private int end;//队尾元素在数组中的索引 public MyQueue() { arr = new Object[10]; elements = 0; front = 0; end = -1; } public MyQueue(int maxSize) { arr = new Object[maxSize]; elements = 0; front = 0; end = -1; } }
2、队列是否为空
标记队列元数量的变量 elements 为 0 即为空
public boolean isEmpty() { return elements == 0; }
3、队列是否已经满了
队列元素个数与数组的长度相等即为满
public boolean isFull() { return elements == arr.length; }
4、获取队头元素
获取数组中索引为 front
的元素
public Object peek() { return arr[front]; }
5、移除队首元素
每次都是移除数组中索引为 front
的元素,下一个元素就变成了队首,即front+1
,队列元素个数elements-1
。共有三种情况要考虑,如果队列已经空了就无须做任何操作,如果已经是最后一个元素,直接将标记位置的变量重置即可,其他情况正常操作。
public Object remove() { if (isEmpty()) { throw new RuntimeException("队列已经是空的,放心使用吧"); } Object value = arr[front++]; //如果已经是最后一个元素了,将指针重置即可 if (elements == 1) { end = -1; front = 0; elements = 0; } else { elements--; } return value; }
6、插入
我们编写一个持续可用的队列,所以要考虑到以下情况。
(1)存储队列的数组满了(队列满了),这个好理解,满了就无法向队尾加入元素了。
(2)因为队列在数组中是连续的,如果队列的元素在数组中最后,需要将元素从队首到队尾移到数组中第一位,也就是将后面的位置空出来(参考下图)。
public void insert(Object value) { //检测队列是否已经满了 if (isFull()) { throw new RuntimeException("队列内元素已达到设定长度"); } //如果后面没有空位置,将余下元素放到数组的头 if (elements > 1 && end == arr.length - 1) { int i = 0; for (; i < elements; i++, front++) { arr[i] = arr[front]; } front = 0; end = i-1; } //其他情况正常向后添加元素 arr[++end] = value; elements++; }
7、测试
public static void main(String[] args) { MyQueue queue = new MyQueue(4); queue.insert(11); queue.insert(12); queue.insert(13); queue.insert(14); queue.remove(); queue.remove(); queue.insert(16); //queue.remove(); //queue.remove(); //queue.insert(19); //queue.insert(20); queue.remove(); queue.remove(); queue.insert(21); queue.insert(22); while (!queue.isEmpty()) { System.out.println(queue.remove()); } }
三、完整代码
package com.jikedaquan.datastruct; public class MyQueue { private Object[] arr; private int elements;//队列元素数量 private int front;//队头元素在数组中的索引 private int end;//队尾元素在数组中的索引 public MyQueue() { arr = new Object[10]; elements = 0; front = 0; end = -1; } public MyQueue(int maxSize) { arr = new Object[maxSize]; elements = 0; front = 0; end = -1; } //从队尾插入 public void insert(Object value) { //检测队列是否已经满了 if (isFull()) { throw new RuntimeException("队列内元素已达到设定长度"); } //如果后面没有空位置,将余下元素放到数组的头 if (elements > 1 && end == arr.length - 1) { int i = 0; for (; i < elements; i++, front++) { arr[i] = arr[front]; } front = 0; end = i-1; } arr[++end] = value; elements++; } //删除数据,从队头删除 public Object remove() { if (isEmpty()) { throw new RuntimeException("队列已经是空的,放心使用吧"); } Object value = arr[front++]; //如果已经是最后一个元素了,将指针重置即可 if (elements == 1) { end = -1; front = 0; elements = 0; } else { elements--; } return value; } //查看数据,从队头查看 public Object peek() { return arr[front]; } //判断是否为空 public boolean isEmpty() { return elements == 0; } public boolean isFull() { return elements == arr.length; } public static void main(String[] args) { MyQueue queue = new MyQueue(4); queue.insert(11); queue.insert(12); queue.insert(13); queue.insert(14); queue.remove(); queue.remove(); queue.insert(16); // queue.remove(); // queue.remove(); // queue.insert(19); // queue.insert(20); queue.remove(); queue.remove(); queue.insert(21); queue.insert(22); while (!queue.isEmpty()) { System.out.println(queue.remove()); } } }
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
浅谈JS的闭包
最近正逢过十一,有了大块的时间,可以给自己充充电。于是便开始了《你不知道的JavaScript 上卷》之旅。最开始的几章描述的是JS的相关编译原理,作用域,以及声明提升的相关知识。这些内容虽然很重要,但是不是本文的重点。本文的重点是作用域的闭包,为什么呢?因为到现在为止,对这个概念还是云里雾里,所以在这里做下记录。 闭包的定义 当函数可以记住并访问所在的词法作用域时,就产生了闭包,即使函数在当前词法作用域之外执行。 这么说,是不是还是有点不懂。那么我们可以换个说法:无论通过何种方法将内部函数传递到词法作用域之外,他都会持有对原始定义作用域的引用,无论在何处执行这个函数,都会使用闭包。 这么讲还不是很懂?没关系,那么我们可以看一下菜鸟教程对闭包的讲解: 闭包是一种保护私有变量的机制,在函数执行时形成私有的作用域,保护里面的私有变量不受外界干扰。直观的说就是形成一个不销毁的栈环境。 还是不太懂? 没关系,让我们来看一下mozilla的定义: 闭包是由函数以及创建该函数的词法环境组合而成。这个环境包含了这个闭包创建时所能访问的所有局部变量 因为原生的JavaScript是不支持私有变量的,所...
- 下一篇
IntelliJ IDEA 安装和配置
一、安装 下载地址:http://www.jetbrains.com/idea 历史版本下载:https://www.jetbrains.com/idea/download/previous.html 下载后直接点击安装即可,没有什么特别需要说明的直接使用默认的即可。 激活说明:有经济条件的还是支持一下直接购买吧,激活码获取地址:http://idea.lanyus.com;也可以到淘宝上去买一个激活码。 二、设置 2.1 编码设置 file->Settings->Editor->File Encodings Global Encoding:UTF-8 Projectt Encoding:UTF-8 Default encoding for properties files:UTF-8 勾选上Transparent native-to-ascii conversion 2.2 代码样式 file-->settings-->Editor-->Font font----consolas size 14 将show only monospaced font...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS8编译安装MySQL8.0.19
- CentOS7,8上快速安装Gitea,搭建Git服务器
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- CentOS关闭SELinux安全模块
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- CentOS8安装MyCat,轻松搞定数据库的读写分离、垂直分库、水平分库
- CentOS8安装Docker,最新的服务器搭配容器使用
- CentOS7,CentOS8安装Elasticsearch6.8.6
- Red5直播服务器,属于Java语言的直播服务器