Java LinkedList作為棧和佇列的使用
阿新 • • 發佈:2020-12-12
最近用java寫一些演算法時,經常遇到要使用棧和佇列結構(比如樹的各種遍歷等等),使用棧的話,Stack已經不被推薦使用了,所以棧和佇列我們通常都是用LinkedList這種雙鏈表結構實現,用的多了自然就開始好奇它的各種操作具體是怎麼實現的?
先下面分別從用法和原始碼角度簡單記錄下如何用LinkedList實現棧和佇列
作為棧使用時,push是入棧,pop / poll是出棧,peek是獲取棧頂元素
具體使用如下示例:
LinkedList<String> stack = new LinkedList<>(); stack.push("a"); stack.push("b"); stack.push("c"); stack.push("d"); System.out.println(stack.peek());//棧為d c b a,輸出:d System.out.println(stack.poll());//棧為d c b a,輸出: System.out.println(stack.pop());//棧為c b a,輸出c
原始碼分析:
在使用LinkedList作為棧時,我們可以去看一下原始碼中push方法的實現,可以看到,push使用的時雙鏈表的頭插法,也就是在連結串列頭部插入元素
public void push(E e) { addFirst(e); } public void addFirst(E e) { linkFirst(e); } private void linkFirst(E e) { final Node<E> f = first; final Node<E> newNode = new Node<>(null, e, f); first = newNode; if (f == null) last = newNode; else f.prev = newNode; size++; modCount++; }
作為佇列使用時,offer是入佇列,poll是出佇列,peek是獲取隊頭元素
但LinkedList實現佇列有兩種用法
①直接使用LinkedList提供的offer和poll來實現出隊、入隊、取隊頭
LinkedList<String> queue = new LinkedList<>(); queue.offer("a"); queue.offer("b"); queue.offer("c"); queue.offer("d"); System.out.println(queue.peek());//佇列為:a b c d,輸出:a System.out.println(queue.poll());//佇列為:a b c d,輸出:a System.out.println(queue.pop());//佇列為:b c d,輸出:
②LinkedList實現了Deque介面,Deque繼承自Queue,所以可以使用父類指向子類的方式來訪問子類方法從而實現佇列。
注意:Queue介面中出佇列只提供了poll方法,所以LinkedList的pop方法就不能使用了。
LinkedList<String> queue = new LinkedList<>();
queue.offer("a");
queue.offer("b");
queue.offer("c");
queue.offer("d");
System.out.println(queue.peek());//佇列為:a b c d,輸出:a
System.out.println(queue.poll());//佇列為:a b c d,輸出:a
原始碼分析:
上面已經貼了peek、poll、pop,這裡就只把offer的原始碼貼出來,可以看到LinkedList作為佇列時,offer方法就是從雙向連結串列尾部新增元素,然後取出時呼叫pop/poll/peek從連結串列頭部取出,從而實現FIFO。
public boolean offer(E e) {
return add(e);
}
public boolean add(E e) {
linkLast(e);
return true;
}
void linkLast(E e) {
final Node<E> l = last;
final Node<E> newNode = new Node<>(l, e, null);
last = newNode;
if (l == null)
first = newNode;
else
l.next = newNode;
size++;
modCount++;
}