雜談"棧"結構:
棧(Stack)是一種插入刪除操作都只能在一個位置上進表,這個位置位於表的末端,叫做棧頂(Top).
對棧的基本操作有push和pop,表示進棧和出棧.也就相當於插入和刪除操作.
棧結構又叫做LIFO(后進先出)表.歸根結底是一個表結構,因此任何能夠實現表結構的方法都能實現棧.
在java語言中,ArrayList和LinkedList都支持棧操作,棧操作都是常數時間的操作,棧的實現方式一般有兩種,一種是使用順序存儲的方式,即使用數組來實現,用ArrayList可以輕易實現棧結構,也可以自己使用數組來實現,一會下面我就用數組來實現棧,第二種是使用鏈式存儲實現,即可以使用LinkedList來實現.
使用數組實現順序棧:
使用arrayList和linkedList實現棧比較簡單,畢竟本身他們就是封裝好的功能,接下來我用數組來實現一個棧結構:
MyStack:
package com.wang.list; import java.util.Arrays; public class MyStack<T> { //使用數組實現這個棧結構
private T[] dataArr; //當前元素的個數
private int theSize; //棧的容量
private static final int DEFAULT_CAPACITY=10; public MyStack(){ clear(); } //初始化數組,默認大小10,元素個數theSize初始化為o
private void clear(){ theSize=0; ensureCapacity(DEFAULT_CAPACITY); } //棧元素容量
public int size(){ return theSize; } private void ensureCapacity(int newCapacity){ if(newCapacity<theSize){ return; } T[] oldArr=dataArr; dataArr=(T[])new Object[newCapacity]; for(int i=0;i<size();i++){ dataArr[i]=oldArr[i]; } } //入棧
public void push(T value){ if(dataArr.length==size()){ ensureCapacity(size()*2); } dataArr[theSize++]=value; } //棧是否為空
public boolean isEmpty(){ return size()==0; } //出棧
public T pop(){ if(isEmpty()){ return null; } T theValue=dataArr[theSize-1]; dataArr[--theSize]=null; return theValue; } //返回棧尾元素
public T peek(){ if(isEmpty()){ return null; } T theValue=dataArr[theSize-1]; return theValue; } }
使用Node()輔助類實現鏈式棧:
package com.wang.list; public class MyStack1<T> { private class Node{ T data; Node next; public Node(T data,Node next){ this.data=data; this.next=next; } } //保存元素個數 private int theSize; //保存棧頂元素 private Node top; public MyStack1(){ top=null; } public MyStack1(T value){ top=new Node(value,null); } public void push(T value){ top=new Node(value,top); theSize++; } public T pop(){ Node old=top; top=top.next; old.next=null; theSize--; return old.data; } public T peek(){ return top.data; } public int size(){ return theSize; } public boolean isEmpty(){ return size()==0; } }
棧的應用:
進制轉換:
比如將十進制下的某個數轉換為二進制中的某個數,則可以對該數進行除2取余操作,然后將余數壓棧,之后再將所有的數出棧,即是所對應的二進制數,這其實是棧對於逆序操作的一個實例.
平衡符號:
檢查那些成對出現的符號是否匹配,比如(),[],{}等
實現過程大概如下:
做一個空棧,讀入字符直到文件末尾.如果字符是一個開放符號(比如"{}"中的"{"),則將其推入棧中.如果字符是一個封閉符號(比如"{}"中的"}"),則判斷棧是否為空,為空則報錯.不為空,則將棧頂元素彈出,判斷彈出元素是否是其對應的開放符號,不是則報錯,在文件結尾,如果棧非空,就報錯.
后綴表達式:
不知道何為后綴表達式,請自行百度,后綴表達式的記法又稱為逆波蘭式,它的求值過程恰好就是從左到右的過程,可以使用一個棧,當見到一個數時就入棧,當遇到一個一個運算符時,就從棧中彈出兩個數進行計算,再將所得結果入棧.最后的到的數就是計算結果.
用於方法調用:
存在方法調用時,比如在一個方法中調用了另一個方法,這時候需要把當前方法一些重要信息記錄並保存下來,保存到一個棧中,然后再跳到新方法中去執行,當方法返回的時候,去查看棧頂的那個保存信息(棧幀),然后進行復原,事實上這是在計算機系統中一個非常重要的應用,上面的全部工作都可以用一個棧來實現.事實上,在實現遞歸的每一種程序語言都是這么干的,所存儲的信息叫做活動記錄,或者說棧幀.這個細說,比較復雜,想深入了解,自己百度吧.