1. 环形队列分析
环形队列是一种复用性极高的数据结构,被使用在许多场景中,如在MySQL数据库的InnoDB存储引擎中的Redo log日志,在DB挂了的时候,提供即使的数据恢复,保证了其持久性。默认便是有四个文件循环写入修改信息。又例如Disruptor消息队列,其任务队列便是一个环形队列,循环写入,写满即覆盖继续写。
逻辑图如下:

环形队列的一个主要特性便是当队列满了之后,回到头部继续push,这里可采用两个指针pushPoint和popPoint进行实现。分析图如下。

2. 代码实现
双向链表实现环形队列
public class RingLinked {
public static void main(String[] args) {
RingLinked<Integer> buffer = new RingLinked<Integer>(4);
buffer.push(1);
buffer.push(2);
buffer.push(3);
buffer.push(4);
System.out.println(buffer.pop());
System.out.println(buffer.pop());
buffer.push(5);
System.out.println(buffer.pop());
}
static class RingLinked<T>{
private Node<T> head;
private int pushPoint;
private int popPoint;
private int size;
private int limit;
public RingLinked(int limit) {
this.limit = limit;
this.pushPoint = 0;
this.popPoint = 0;
this.size = 0;
this.head = new Node<T>(null);
Node<T> h = head;
for (int i = 0; i < (limit-1); i++) {
Node<T> node = new Node<T>(null);
h.next = node;
node.last = h;
h = node;
}
}
public void push(T value){
if(size == limit) {
throw new RuntimeException("队列已满,无法push");
}
//找到对应Node
Node<T> node = node(pushPoint);
// 直接替换value即可!
node.value = value;
pushPoint = nextIndex(pushPoint);
size++;
}
public T pop(){
if(size==0) {
throw new RuntimeException("队列已空,无值pop");
}
Node<T> node = node(popPoint);
popPoint = nextIndex(popPoint);
size --;
T result = node.value;
node.value = null;
return result;
}
public boolean isEmpty(){
return size==0;
}
public int size() {
return size;
}
/**
* 遍历Node节点
* @param index
* @return
*/
public Node<T> node(int index) {
Node<T> x = head;
for (int i = 0; i < index; i++) {
x = x.next;
}
return x;
}
public int nextIndex(int index) {
return index < (limit - 1) ? index+1 : 0;
}
}
/**
* 节点
*/
static class Node<T> {
private T value;
private Node<T> next;
private Node<T> last;
public Node(T value) {
this.value = value;
}
}
}
数组实现环形队列:
public class RingArray {
public static void main(String[] args) {
MyQueue queue = new MyQueue(4);
queue.push(0);
queue.push(1);
queue.push(2);
queue.push(3);
System.out.println(queue.pop());
queue.push(4);
}
}
/**
* 环形队列由数组实现
*/
class MyQueue{
private Object[] arr;
private int pushPoint;
private int popPoint;
private int size;
private int limit;
public MyQueue(int limit){
this.arr = new Object[limit];
pushPoint = 0;
popPoint = 0;
size = 0;
this.limit = limit;
}
public void push(Object value) {
if(size == limit) {
throw new RuntimeException("队列已满,请稍后再加");
}
arr[pushPoint] = value;
pushPoint = nextIndex(pushPoint);
size ++ ;
}
public Object pop() {
if(size == 0) {
throw new RuntimeException("队列已空,请稍后再取");
}
Object result = arr[popPoint];
popPoint = nextIndex(popPoint);
size --;
return result;
}
private boolean isEmpty(){
return size==0;
}
private int nextIndex(int i){
return i < limit-1 ? i+1:0;
}
}
思路如下图:

3. 后言
无论是环形队列还是栈或者哈希表,实则数据结构的实现要么是数组要么是链表或者数组+链表。
本文详细介绍了环形队列的基本概念与应用场景,并通过双向链表与数组两种方式实现了环形队列,展示了如何利用环形队列解决实际问题。
392

被折叠的 条评论
为什么被折叠?



