[英]Best implementation of Java Queue?
我正在(在 Java 中)研究遞歸圖像處理算法,該算法從中心點向外遞歸遍歷圖像的像素。
不幸的是,這會導致堆棧溢出。 所以我決定切換到基於隊列的算法。
現在,這一切都很好,但考慮到它的隊列將在很短的時間內分析數千個像素,同時不斷彈出和推送,而不保持可預測的狀態(它可能在長度 100,和 20000),隊列實現需要具有顯着快速的彈出和推送能力。
鏈表看起來很有吸引力,因為它能夠將元素推入自身而不重新排列列表中的任何其他內容,但為了使其足夠快,它需要輕松訪問其頭部和尾部(或第二個) -last 節點,如果它不是雙向鏈接的)。 遺憾的是,我找不到任何與 Java 中鏈表的底層實現相關的信息,所以很難說鏈表是否真的是要走的路......
這讓我想到了我的問題。 對於我打算做的事情,Java 中 Queue 接口的最佳實現是什么? (我不希望編輯甚至訪問隊列的頭部和尾部以外的任何東西——我不想做任何重新排列或任何事情。另一方面,我確實打算做很多推動並彈出,並且隊列的大小會發生很大變化,因此預分配效率低下)
采用:
Queue<Object> queue = new LinkedList<>();
JAVA 定義了接口Queue
, LinkedList提供了實現。
您可以使用.add(E e)
將元素附加到隊列的末尾,並使用.remove()
出列並檢索隊列的頭部(第一個元素)。
它還維護對 Head 和 Tail 元素的引用,您可以分別通過.getFirst()
和.getLast()
獲取.getFirst()
。
感謝@Snicolas 提出隊列接口的建議
如果您使用 LinkedList,請小心。 如果你像這樣使用它:
LinkedList<String> queue = new LinkedList<String>();
那么你可以違反隊列定義,因為可以刪除除第一個之外的其他元素(LinkedList中有這樣的方法)。
但是如果你像這樣使用它:
Queue<String> queue = new LinkedList<String>();
應該沒問題,因為這是提醒用戶,插入應該只發生在后面,刪除應該只發生在前面。
您可以通過將 LinkedList 類擴展到一個 PureQueue 類來克服 Queue 接口的有缺陷實現,該類拋出任何有問題的方法的 UnsupportedOperationException。 或者,您可以通過只創建一個字段類型為 LinkedList 對象列表的 PureQueue 來采用聚合方法,唯一的方法是默認構造函數、復制構造函數、 isEmpty()
、 size()
、 add(E element)
, remove()
和element()
。 所有這些方法都應該是單行的,例如:
/**
* Retrieves and removes the head of this queue.
* The worstTime(n) is constant and averageTime(n) is constant.
*
* @return the head of this queue.
* @throws NoSuchElementException if this queue is empty.
*/
public E remove()
{
return list.removeFirst();
} // method remove()
查看Deque接口,它提供了兩端的插入/刪除。 LinkedList 實現了該接口(如上所述),但對於您的使用而言,ArrayDeque 可能更好——您不會產生為每個節點分配常量對象的成本。 再說一次,您使用哪種實現可能無關緊要。
正常多態性的好處開始發揮作用:針對 Deque 接口而不是它的任何特定實現編寫的美妙之處在於,您可以非常輕松地切換實現以測試哪個實現最好。 只需在其中使用new
更改行,其余代碼保持不變。
在 Java 中實現 Stack 和 Queue 時,最好使用 ArrayDeque 而不是 LinkedList。 當用作堆棧時,ArrayDeque 可能比 Stack 接口更快(而 Stack 是線程安全的),當用作隊列時比 LinkedList 更快。 看看這個鏈接Use ArrayDeque 而不是 LinkedList 或 Stack 。
我認為您可以通過簡單的實現來解決問題
package DataStructures;
public class Queue<T> {
private Node<T> root;
public Queue(T value) {
root = new Node<T>(value);
}
public void enque(T value) {
Node<T> node = new Node<T>(value);
node.setNext(root);
root = node;
}
public Node<T> deque() {
Node<T> node = root;
Node<T> previous = null;
while(node.next() != null) {
previous = node;
node = node.next();
}
node = previous.next();
previous.setNext(null);
return node;
}
static class Node<T> {
private T value;
private Node<T> next;
public Node (T value) {
this.value = value;
}
public void setValue(T value) {
this.value = value;
}
public T getValue() {
return value;
}
public void setNext(Node<T> next) {
this.next = next;
}
public Node<T> next() {
return next;
}
}
}
如果您知道隊列中可能的項目數量的上限,則循環緩沖區比 LinkedList 更快,因為 LinkedList 為隊列中的每個項目創建一個對象(鏈接)。
但是,如果您仍然想使用遞歸算法,則可以將其更改為“尾遞歸” ,這可能在 JVM 中進行了優化以避免堆棧溢出。
O(1) 訪問第一個和最后一個節點。
class Queue {
private Node head;
private Node end;
public void enqueue(Integer data){
Node node = new Node(data);
if(this.end == null){
this.head = node;
this.end = this.head;
}
else {
this.end.setNext(node);
this.end = node;
}
}
public void dequeue (){
if (head == end){
end = null;
}
head = this.head.getNext();
}
@Override
public String toString() {
return head.getData().toString();
}
public String deepToString() {
StringBuilder res = new StringBuilder();
res.append(head.getData());
Node cur = head;
while (null != (cur = cur.getNext())){
res.append(" ");
res.append(cur.getData());
}
return res.toString();
}
}
class Node {
private Node next;
private Integer data;
Node(Integer i){
data = i;
}
public Integer getData() {
return data;
}
public Node getNext() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
}
這是帶有Iterator和Iterable接口的隊列實現
隊列大小會隨着它變滿而增加
隊列接口
package com.practice.ds.queue;
import com.practice.ds.queue.exception.QueueException;
public interface QueueInterface<T> {
public boolean empty();
public void enqueue(T item);
public void dequeue() throws QueueException;
public T front() throws QueueException;
public void clear();
}
自定義異常類
package com.practice.ds.queue.exception;
public class QueueException extends Exception {
private static final long serialVersionUID = -884127093599336807L;
public QueueException() {
super();
}
public QueueException(String message) {
super(message);
}
public QueueException(Throwable e) {
super(e);
}
public QueueException(String message, Throwable e) {
super(message, e);
}
}
隊列的實現
package com.practice.ds.queue;
import java.util.Iterator;
import com.practice.ds.queue.exception.QueueException;
public class Queue<T> implements QueueInterface<T>, Iterable<T> {
private static final int DEFAULT_CAPACITY = 10;
private int current = 0;
private int rear = 0;
private T[] queueArray = null;
private int capacity = 0;
@SuppressWarnings("unchecked")
public Queue() {
capacity = DEFAULT_CAPACITY;
queueArray = (T[]) new Object[DEFAULT_CAPACITY];
rear = 0;
current = 0;
}
@Override
public boolean empty() {
return capacity == current;
}
@Override
public void enqueue(T item) {
if(full())
ensureCapacity();
queueArray[current] = item;
current++;
}
@Override
public void dequeue() throws QueueException {
T dequeuedItem = front();
rear++;
System.out.println("Dequed Item is " + dequeuedItem);
}
@Override
public T front() throws QueueException {
return queueArray[rear];
}
@Override
public void clear() {
for (int i = 0; i < capacity; i++)
queueArray[i] = null;
current = 0;
rear = 0;
}
@SuppressWarnings("unchecked")
private void ensureCapacity() {
if (rear != 0) {
copyElements(queueArray);
} else {
capacity *= 2;
T[] tempQueueArray = (T[]) new Object[capacity];
copyElements(tempQueueArray);
}
current -= rear;
rear = 0;
}
private void copyElements(T[] array) {
for (int i = rear; i < current; i++)
array[i - rear] = queueArray[i];
queueArray = array;
}
@Override
public Iterator<T> iterator() {
return new QueueItearator<T>();
}
public boolean full() {
return current == capacity;
}
private class QueueItearator<T> implements Iterator<T> {
private int index = rear;
@Override
public boolean hasNext() {
return index < current;
}
@SuppressWarnings("unchecked")
@Override
public T next() {
return (T) queueArray[index++];
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.