1. 程式人生 > 其它 >Java LinkedList作為棧和佇列的使用

Java LinkedList作為棧和佇列的使用

技術標籤:java集合java佇列queuestack

最近用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++;
}