看動畫學演算法之:棧stack

flydean發表於2021-10-12

簡介

棧應該是一種非常簡單並且非常有用的資料結構了。棧的特點就是先進後出FILO或者後進先出LIFO。

實際上很多虛擬機器的結構都是棧。因為棧在實現函式呼叫中非常的有效。

今天我們一起來看學習一下棧的結構和用法。

棧的構成

棧一種有序的線性表,只能在一端進行插入或者刪除操作。這一端就叫做top端。

定義一個棧,我們需要實現兩種功能,一種是push也就是入棧,一種是pop也就是出棧。

當然我們也可以定義一些其他的輔助功能,比如top:獲取棧上最頂層的節點。isEmpty:判斷棧是否為空。isFull:判斷棧是否滿了之類。

先看下入棧的動畫:

再看下出棧的動畫:

棧的實現

具有這樣功能的棧是怎麼實現呢?

一般來說棧可以用陣列實現,也可以用連結串列來實現。

使用陣列來實現棧

如果使用陣列來實現棧的話,我們可以使用陣列的最後一個節點作為棧的head。這樣在push和pop棧的操作的時候,只需要修改陣列中的最後一個節點即可。

我們還需要一個topIndex來儲存最後一個節點的位置。

實現程式碼如下:

public class ArrayStack {

    //實際儲存資料的陣列
    private int[] array;
    //stack的容量
    private int capacity;
    //stack頭部指標的位置
    private int topIndex;

    public ArrayStack(int capacity){
        this.capacity= capacity;
        array = new int[capacity];
        //預設情況下topIndex是-1,表示stack是空
        topIndex=-1;
    }

    /**
     * stack 是否為空
     * @return
     */
    public boolean isEmpty(){
        return topIndex == -1;
    }

    /**
     * stack 是否滿了
     * @return
     */
    public boolean isFull(){
        return topIndex == array.length -1 ;
    }

    public void push(int data){
        if(isFull()){
            System.out.println("Stack已經滿了,禁止插入");
        }else{
            array[++topIndex]=data;
        }
    }

    public int pop(){
        if(isEmpty()){
            System.out.println("Stack是空的");
            return -1;
        }else{
            return array[topIndex--];
        }
    }
}

使用動態陣列來實現棧

上面的例子中,我們的陣列大小是固定的。也就是說stack是有容量限制的。

如果我們想構建一個無限容量的棧應該怎麼做呢?

很簡單,在push的時候,如果棧滿了,我們將底層的陣列進行擴容就可以了。

實現程式碼如下:

public void push(int data){
        if(isFull()){
            System.out.println("Stack已經滿了,stack擴容");
            expandStack();
        }
        array[++topIndex]=data;
    }

    //擴容stack,這裡我們簡單的使用倍增方式
    private void expandStack(){
        int[] expandedArray = new int[capacity* 2];
        System.arraycopy(array,0, expandedArray,0, capacity);
        capacity= capacity*2;
        array= expandedArray;
    }

當然,擴容陣列有很多種方式,這裡我們選擇的是倍增方式。

使用連結串列來實現

除了使用陣列,我們還可以使用連結串列來建立棧。

使用連結串列的時候,我們只需要對連結串列的head節點進行操作即可。插入和刪除都是處理的head節點。

public class LinkedListStack {

    private Node headNode;

    class Node {
        int data;
        Node next;
        //Node的建構函式
        Node(int d) {
            data = d;
        }
    }

    public void push(int data){
        if(headNode == null){
            headNode= new Node(data);
        }else{
            Node newNode= new Node(data);
            newNode.next= headNode;
            headNode= newNode;
        }
    }

    public int top(){
        if(headNode ==null){
            return -1;
        }else{
            return headNode.data;
        }
    }

    public int pop(){
        if(headNode ==null){
            System.out.println("Stack是空的");
            return -1;
        }else{
            int data= headNode.data;
            headNode= headNode.next;
            return data;
        }
    }

    public boolean isEmpty(){
        return headNode==null;
    }
}

本文的程式碼地址:

learn-algorithm

本文已收錄於 http://www.flydean.com/10-algorithm-stack/

最通俗的解讀,最深刻的乾貨,最簡潔的教程,眾多你不知道的小技巧等你來發現!

歡迎關注我的公眾號:「程式那些事」,懂技術,更懂你!

相關文章