聲明:碼字不易,轉載請註明出處,歡迎文章下方討論交流。
前言:Java數據結構與算法專題會不定時更新,歡迎各位讀者監督。本文介紹數據結構中的棧的概念、存儲結構、棧的特色以及棧的適用場景,另外會穿插介紹面試中的一些經典問題供讀者參考。java
棧是一種有着特殊操做規則的數據結構——後進先出(LIFO,Last In First Out),這也是棧的最重要的一個特色。棧又叫作堆棧(Stack),這裏說明一下不要講堆棧和堆(Heap)的概念混淆,事實上棧和堆是兩個不一樣的概念
,後面的文章會介紹堆。通常來說,棧有兩個操做:一個是進棧(Push),也叫壓棧或入棧,另外一個是出棧(Pop)或叫彈棧、退棧。面試
棧通常使用一段連續的空間進行存儲,一般預先分配一個長度能夠簡單的使用數組來實現,具體存儲結構如圖:算法
經過上圖能夠看到只有一個方向能夠對棧內元素進行操做,棧中最下面的元素位置叫棧底,一般定義爲數組的第0個元素,最上面的元素叫棧頂。通常而言,定義一個棧須要聲明棧的促使容量,當放入的棧中的元素大於棧的容量時,就須要考慮擴容,不然溢出。編程
如下是棧的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());//拋出異常,提示爲空棧 } }
棧的特色顯而易見,只能從一段進行元素的壓入和彈出,先進去的後出來。編程語言
根據棧先入後出的特色,如下場景的問題適合用棧來解決:函數
1)逆序輸出
將全部元素依次壓入棧中,而後依次彈出便可測試
2)編譯器的語法檢查
在大多數編程語言中,通常括號都是成對出現,遇到括號的左半部分,則進行入棧(push)操做,遇到括號右半部分則當即與棧頂(top)元素匹配,匹配成功則彈棧(pop),不然報錯。this
3)數制轉換(10進制轉換任意進制)
數制轉換一般採用取餘倒置,此處再也不展開。
4)方法調用編寫的程序在進行方法(函數)調用時,CPU會完成對方法的壓棧操做,等方法執行結束後,對應的CPU會完成對方法的彈棧操做。固然除此以外,cpu產生中斷後,首先進行壓棧操做,將打斷的程序運行數據一一入棧,中斷服務程序執行完後把入棧的運行數據按照相反的順序依次出棧,恢復中斷前的運行狀態,CPU 開始返回中斷前的地方繼續運行。