Stacks and Queues

stack:last in first out (LIFO)
queue: first in fist out (FIFO)

stack API

  • linked-list stack implementation
public class LinkedStackofStrings{
    private Node first = null;
    private class Node(){
        String item;
        Node next;
    }

    //insert a new string into stack
    public void push(String item){
        //在鏈表的頭結(jié)點入棧
        Node oldfirst = first;
        first = new Node();
        first.item = item;
        first.next = oldfirst;
    }
    
    //remove and return the string most recently added
    public String pop(){
        String item = first.item;
        first = first.next;
        return item;
    }
    
    //is the stack empty?
    public boolean isEmpty(){
        return first==null;
    }
}
  • array stack implementation
    s[N]為棧頂,為空
public class FixedCapacityStackofStrings{
    private String[] s;
    private int N = 0;
    //固定大小的棧
    public FixedCapacityStackofStrings(int capacity){
        s = new String[capacity];
    }
    //insert a new string into stack
    public void push(String item){
        s[N++] =item; 
    }
    
    //remove and return the string most recently added
    public String pop(){
        return s[--N]; 
    }
    
    //is the stack empty?
    public boolean isEmpty(){
        return N == 0;
    }
}

問題:
1.underflow:從空棧pop時
2.overflow:向已滿的棧push時;解決方法為resize數(shù)組大小
3.空item:解決方法為允許null入棧
4.loitering(內(nèi)存泄漏?):當(dāng)pop時,依然有指向object的指針;更改為:

public String pop(){
    String item = s[--N];
    s[N] == null;
    return item;
}

resizing array

但是上述數(shù)組的實現(xiàn)需要用戶提供棧的固定容量,但一般沒有人能確定棧的最大容量,因此最好能隨時增大數(shù)組。

  • first try

push:array size加一;
pop:array size減一;

too expensive,每次改變數(shù)組大小時都要把所有項復(fù)制到新數(shù)組中,因此插入N項的時間復(fù)雜度為1+2+3+4+……+N,約為N的平方。

因此最好保證resize array不那么頻繁。

  • 改進

如果數(shù)組滿了,則將數(shù)組的大小變?yōu)樵瓉淼亩丁?/p>

public ResizingArrayStackofStrings{
    private s = new String[1];
    public void push(String item){
        if(N==s.length) resize(2*s.length);
        s[N++] = item;
    }

    public void resize(int capacity){
        String[] copy = new Stirng[2*capacity];
        for(int i = 0;i<s.length;i++){
            copy[i] = s[i];
        }
        s = copy;
    }
}

此時插入N項所需的時間復(fù)雜度為2+4+8+……+N,即每次復(fù)制的item個數(shù)為2的k次方,則1+2+4+8+……+2的k次方為2的k+1次方,即2N(N為2的k次方),因此時間復(fù)雜度為N,相比每插入一項就增大數(shù)組size的N平方有了很大改進。

那縮小數(shù)組呢?

  • first try

當(dāng)數(shù)組內(nèi)容變?yōu)樵瓉淼囊话霑r將數(shù)組縮小至原來的一半。
但當(dāng)數(shù)組滿的時候,push會加倍數(shù)組的長度,pop又會減半數(shù)組的長度,就這么交替地push、pop、push、pop,每次操作時間復(fù)雜度都為N

  • efficient solution

當(dāng)數(shù)組1/4滿時,將數(shù)組長度減半.

public String pop(){
    String item = s[--N];
    s[N] = null;
    if(N>0 && N == s.length/4) resize(s.length/2);
    return item;
}

這樣array的長度是在25%到100%之間。

因此,resizing arrays的push和pop時間復(fù)雜度都為O(N)。

Queue API

  • linked-list implementation
public class LinkedListQueueofStrings{
    private class Node{
        String item;
        Node next;
    }
    public void enqueue(String item){
        Node oldlast = last;
        Node last = new Node();
        last.item = item;
        last.next = null;
        if(isEmpty()) first = last;
        else  oldlast.next = last;
    }

    public String dequeue(){
        String item = first.item;
        first = first.next;
        if(isEmpty()) last = null;
    }

    public boolean isEmpty(){
        return first == null;
    }
}
  • resizing arrays
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容