Java數據結構與算法[原創]——棧

聲明:碼字不易,轉載請註明出處,歡迎文章下方討論交流。

前言:Java數據結構與算法專題會不定時更新,歡迎各位讀者監督。本文介紹數據結構中的棧的概念、存儲結構、棧的特色以及棧的適用場景,另外會穿插介紹面試中的一些經典問題供讀者參考。java

1.棧的相關概念

棧是一種有着特殊操做規則的數據結構——後進先出(LIFO,Last In First Out),這也是棧的最重要的一個特色。棧又叫作堆棧(Stack),這裏說明一下不要講堆棧和堆(Heap)的概念混淆,事實上棧和堆是兩個不一樣的概念,後面的文章會介紹堆。通常來說,棧有兩個操做:一個是進棧(Push),也叫壓棧或入棧,另外一個是出棧(Pop)或叫彈棧、退棧。面試

2.棧的存儲結構

棧通常使用一段連續的空間進行存儲,一般預先分配一個長度能夠簡單的使用數組來實現,具體存儲結構如圖:
圖片描述算法

經過上圖能夠看到只有一個方向能夠對棧內元素進行操做,棧中最下面的元素位置叫棧底,一般定義爲數組的第0個元素,最上面的元素叫棧頂。通常而言,定義一個棧須要聲明棧的促使容量,當放入的棧中的元素大於棧的容量時,就須要考慮擴容,不然溢出。編程

3.java代碼實現

如下是棧的java代碼,此處以整型元素爲例。數組

import java.util.Arrays;

public class Stack {
    private int size = 0;  //棧頂位置
    private int[] array;
    
    public Stack(){
        this(10);
    }
    public Stack(int init) {   
        if(init <= 0){
            init = 10;
        }
        array = new int[init];
    }
    
    /**
     * 入棧操做
     * @param item 入棧的元素
     */
    public void push(int item){
        if(size == array.length){
            array = Arrays.copyOf(array, size*2);   //擴容操做
        }
        array[size++] = item;
    }
    
    /**
     * 獲取棧頂元素,但棧頂元素不出棧
     * @return 棧頂元素
     */
    public int peek(){
        if(size == 0){  //空棧
            throw new IndexOutOfBoundsException("棧是空的");
        }
        return array[size-1];
    }
    
    /**
     * 出棧,同時獲取棧頂元素
     * @return
     */
    public int pop(){
        int item = peek();  //獲取棧頂元素
        size--;  //直接使元素個數減1,不用清除元素,下次入棧會覆蓋舊元素的值
        return item;
    }
    
    /**
     * 判斷棧是否已滿
     * @return
     */
    public boolean isFull(){
        return size == array.length;
    }
    
    /**
     * 判斷棧是否爲空
     * @return
     */
    public boolean isEmpty(){
        return size == 0;
    }
    
    public int getSize(){
        return size;
    }    
}

測試程序:數據結構

public class StackTest {
    public static void main(String[] args) {
        Stack s = new Stack(3);  //設置棧的初始容量爲3
        s.push(2);
        s.push(5);
        s.push(7);
        s.push(10);    //此時擴容,自底向頂 2—>5->7->10
        System.out.println("棧頂位置是:"+s.getTop()); //棧頂指針爲4,數組長度爲3*2=6        
        System.out.println("獲取棧頂元素:"+s.peek());  //獲取但不彈棧
        System.out.println("彈出棧頂元素:"+s.pop());//彈棧返回10,自底向頂 2—>5->7
        System.out.println("彈出棧頂元素:"+s.pop());//彈棧返回7,自底向頂 2—>5
        s.push(66);   //入棧後,自底向頂 2—>5->66
        System.out.println("彈出棧頂元素:"+s.pop());//彈棧返回66
        System.out.println("彈出棧頂元素:"+s.pop());//彈棧返回5
        System.out.println("彈出棧頂元素:"+s.pop());//彈棧返回2
        System.out.println("彈出棧頂元素:"+s.pop());//拋出異常,提示爲空棧
    }
}

4.棧的特色

棧的特色顯而易見,只能從一段進行元素的壓入和彈出,先進去的後出來。編程語言

5.棧的應用場景

根據棧先入後出的特色,如下場景的問題適合用棧來解決:函數

1)逆序輸出
將全部元素依次壓入棧中,而後依次彈出便可測試

2)編譯器的語法檢查
在大多數編程語言中,通常括號都是成對出現,遇到括號的左半部分,則進行入棧(push)操做,遇到括號右半部分則當即與棧頂(top)元素匹配,匹配成功則彈棧(pop),不然報錯。this

3)數制轉換(10進制轉換任意進制)
數制轉換一般採用取餘倒置,此處再也不展開。

4)方法調用編寫的程序在進行方法(函數)調用時,CPU會完成對方法的壓棧操做,等方法執行結束後,對應的CPU會完成對方法的彈棧操做。固然除此以外,cpu產生中斷後,首先進行壓棧操做,將打斷的程序運行數據一一入棧,中斷服務程序執行完後把入棧的運行數據按照相反的順序依次出棧,恢復中斷前的運行狀態,CPU 開始返回中斷前的地方繼續運行。

相關文章
相關標籤/搜索