环形队列是一种复用性极高的数据结构,被使用在许多场景中,如在MySQL数据库的InnoDB存储引擎中的Redo log日志,在DB挂了的时候,提供即使的数据恢复,保证了其持久性。默认便是有四个文件循环写入修改信息。又例如Disruptor消息队列,其任务队列便是一个环形队列,循环写入,写满即覆盖继续写。
逻辑图如下:
环形队列的一个主要特性便是当队列满了之后,回到头部继续push,这里可采用两个指针pushPoint和popPoint进行实现。分析图如下。
双向链表实现环形队列
public class Ringlinked { public static void main(String[] args) { Ringlinkedbuffer = new Ringlinked (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 { private Node 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 (null); Node h = head; for (int i = 0; i < (limit-1); i++) { Node node = new Node (null); h.next = node; node.last = h; h = node; } } public void push(T value){ if(size == limit) { throw new RuntimeException("队列已满,无法push"); } //找到对应Node Node node = node(pushPoint); // 直接替换value即可! node.value = value; pushPoint = nextIndex(pushPoint); size++; } public T pop(){ if(size==0) { throw new RuntimeException("队列已空,无值pop"); } Node 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; } public Node node(int index) { Node 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 { private T value; private Node next; private Node 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; } }
思路如下图:
无论是环形队列还是栈或者哈希表,实则数据结构的实现要么是数组要么是链表或者数组+链表。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)