网站首页 > java教程 正文
上一篇中基于数组实现了一个普通的队列手写java数据结构(普通队列-数组)这个普通队列的出队操作时间复杂度是O(n)级别的
我们用一个容量为8的数组data来实现一个队列,此时队列中已经入队a,b,c,d,e五个元素,a处于队首位置,e处于队尾位置。此时我们将a元素进行出队操作,那么剩余的元素则需要向左移动。所以这个普通队列的出队操作时间复杂度是O(n)级别的

对于这种情况我们可能会想,我们能不能不移动剩余元素,实现一个性能更好的队列呢?
接下来我们就实现一个循环队列来解决这个问题。
我们先来分析一下如何实现一个循环队列:
仍旧以上面的图示进行分析,当队首元素a出队以后,剩余元素此时不进行移动。我们定义两个标识front 和 tail
- front:标识队首位置,如下图元素b此时为队首元素
- tail:标识下次入队时元素插入的位置,如下图下次入队时元素插入位置为索引5的位置
那么之后进行出队、入队操作后我们只需要维护front、tail就可以了。
- 出队:front往后移动一个位置
- 入队:tai往后移动一个位置
接下来我们在分析一下特殊情况:
- 初始情况下,队列中没有任何元素时,front和tail都指向同一个位置,也就是说如果front == tail队列为空
2.
如果此时再次入队一个元素h,根据我们前面说的,tail需要往后移动一个位置。而此时tail++就会造成新的tail值超出了data数组的索引范围。既然我们要实现的是循环队列,那么对于此时这种情况我们肯定要让它循环起来。我们就要判断这个数组实现的队列是否已满,如果没有满的话说明front前面有空余的位置,我们需要将tail指向front前面的位置。
tail的值我们总结出计算方式为:tail = (tail + 1) % data.length
比如对于上面的情况tail = 7,此时入队元素h,tail = (7 + 1) % 8; tail = 0
3.
如上这种情况,如果此时再次入队一个元素,tail元素再次往后移动一个位置时那么此时tail == front,而之前我们分析过tail == front时队列为空。而此时tail == front时队列是满的,这就会产生冲突。因此当(tail + 1)%data.leng == front的时候我们可以判定队列是满的,此时我们将tail位置闲置,浪费掉这个空间不再插入元素。此时,队列已满。
下面我们用代码实现一下:
public interface Queue<E> {
void enqueue(E e);
E dequeue();
E getFront();
int getSize();
boolean isEmpty();
}
public class LoopQueue<E> implements Queue<E> {
//声明一个数组data用于保存数据
private E[] data;
//声明队首和队尾指针变量
private int front,tail;
//size用于表示队列元素个数
private int size;
//指定容量的构造函数
public LoopQueue(int capacity){
//加一是因为循环队列会浪费一个空间位置
data = (E[]) new Object[capacity + 1];
front = 0;
tail = 0;
size = 0;
}
//无参构造函数,默认容量为10
public LoopQueue() {
this(10);
}
// 扩容方法
private void resize(int newCapacity){
//新建一个扩容后的数组
E[] newData = (E[]) new Object[newCapacity+1];
//将原数组data变量保存到新数组中,这里要注意按照队列的顺序进行保存
for(int i = 0;i < size; i++){
newData[i] = data[(i+front) % data.length];
}
data = newData;
front = 0;
tail = size;
}
//入队
@Override
public void enqueue(E e) {
//首先判断队列是否已满,如果已满我们对其进行扩容
if((tail + 1) % data.length == front){
//扩容原来两倍
resize(getCapacity()*2);
}
//将新元素插入到tail的位置
data[tail] = e;
//更新tail的值
tail = (tail + 1) % data.length;
size++;
}
//出队
@Override
public E dequeue() {
if(isEmpty()){
throw new IllegalArgumentException("empty");
}
//获取队首元素
E ret = data[front];
//内存回收
data[front] = null;
//更新front值
front = (front + 1) % data.length;
size--;
//缩容
if(size == (getCapacity()/4) && getCapacity() / 2 != 0){
resize(getCapacity()/2);
}
return ret;
}
//查看队首元素
@Override
public E getFront() {
if(isEmpty()){
throw new IllegalArgumentException("empty");
}
return data[front];
}
//队列长度
@Override
public int getSize() {
return size;
}
//队列是否为空
@Override
public boolean isEmpty() {
return front == tail;
}
//队列容量
public int getCapacity(){
return data.length - 1;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("loopqueue:");
sb.append("front[");
for(int i = front;i != tail;i = (i + 1) % data.length){
sb.append(data[i]);
if((i + 1) % data.length != tail){
sb.append(",");
}
}
sb.append("]end");
return sb.toString();
}
}
猜你喜欢
- 2024-09-11 阿里架构师剖析:Redis常用数据类型对应的数据结构
- 2024-09-11 聊聊经典数据结构HashMap,逐行分析每一个关键点
- 2024-09-11 压箱底Redis面试集-48.Redis 的 ListPack 数据结构是什么?
- 2024-09-11 JAVA进阶知识学习-day03 数据结构&List集合&Set集合
- 2024-09-11 Java数据结构面试必问:HashMap 底层实现原理分析
- 2024-09-11 Java路径-31-Java数据结构(我的世界java路径错误怎么办)
- 2024-09-11 《数据结构》第九篇、java中ArrayList源码解析
- 2024-09-11 JDK源码分析--Object(jdk1.8源码详细介绍)
- 2024-09-11 「Java数据结构」Java对象的比较(java对比两个对象属性的变化)
- 2024-09-11 动图+源码,演示Java中常用数据结构执行过程及原理
欢迎 你 发表评论:
- 12-03win10系统怎么修复(windows10怎么修复)
- 12-03电脑回收站图标不见了(电脑桌面上的回收站图标不见了怎么办)
- 12-03电脑怎么选(电脑怎么选定文字)
- 12-03vivo应用商店官方app下载(vivo应用商店下载安装官方正版)
- 12-03usb无线网卡驱动下载win7(usb无线网卡驱动安装包)
- 12-03怎样设置无线路由器桥接功能
- 12-03免费硬盘数据恢复工具有哪些
- 12-03桌面显卡性能天梯图快科技(桌面显卡天梯图 快科技)
- 最近发表
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)

本文暂时没有评论,来添加一个吧(●'◡'●)