看動畫學算法之:棧stack

簡介

棧應該是一種非常簡單並且非常有用的數據結構了。棧的特點就是先進後出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

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

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

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