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){
        //在鏈表的頭結點入棧
        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數組大小
3.空item:解決方法為允許null入棧
4.loitering(內存泄漏?):當pop時,依然有指向object的指針;更改為:

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

resizing array

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

  • first try

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

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

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

  • 改進

如果數組滿了,則將數組的大小變為原來的二倍。

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

那縮小數組呢?

  • first try

當數組內容變為原來的一半時將數組縮小至原來的一半。
但當數組滿的時候,push會加倍數組的長度,pop又會減半數組的長度,就這么交替地push、pop、push、pop,每次操作時間復雜度都為N

  • efficient solution

當數組1/4滿時,將數組長度減半.

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時間復雜度都為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
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容