棧(stack)又名堆棧,它是一種運算受限的線性表。其限制是僅允許在表的一端進行插入和刪除運算。這一端被稱爲棧頂,相對地,把另一端稱爲棧底。向一個棧插入新元素又稱作進棧、入棧或壓棧,它是把新元素放到棧頂元素的上面,使之成爲新的棧頂元素;從一個棧刪除元素又稱作出棧或退棧,它是把棧頂元素刪除掉,使其相鄰的元素成爲新的棧頂元素。
棧只允許訪問一個數據項:即最後插入的數據。移除這個數據項後才能訪問倒數第二個插入的數據項。它是一種“後進先出”的數據結構。
棧最基本的操作是出棧、入棧,還有其他擴展操作,如查看棧頂元素,判斷棧是否爲空、是否已滿,讀取棧的大小等
先看一下棧(圖解析),在看代碼
接下來看棧的代碼
public class Stack<E> {
private int length;
private int top;
private Object[] objArray;
//構造方法
public Stack(int lenth){
if (lenth <= 0) throw new IllegalArgumentException("請不要傳入0一下的數");
objArray = new Object[lenth];
this.top = -1;
this.length = lenth;
}
//入棧 棧頂元素加一
public void push(E e) throws Exception {
if(isFull()){
//各位同學,我就不自定異常了
System.out.println("棧滿了,別加了,先擴大容量");
throw new Exception();
}
objArray[++top] = e;
}
//出棧 棧頂元素減一
public Object pop() throws Exception {
if(isEmpty()){
System.out.println("棧空了,別減了,先加入元素");
//各位同學,我就不自定異常了
throw new Exception();
}
return objArray[top--];
}
//判斷棧是否是空
public Boolean isEmpty(){
return top == -1 ? true : false;
}
//查看棧的頂部元素
public Object view(){
return objArray[top];
}
//判斷是否棧滿
public Boolean isFull(){
return top == length -1 ? true : false;
}
public static void main(String[] args) throws Exception {
Stack<Integer> integerStack = new Stack<Integer>(5);
integerStack.push(Integer.parseInt("1"));
integerStack.push(Integer.parseInt("2"));
integerStack.push(Integer.parseInt("3"));
integerStack.push(Integer.parseInt("4"));
Object view = integerStack.view();
System.out.println(view);
integerStack.pop();
integerStack.pop();
integerStack.pop();
integerStack.pop();
integerStack.pop();
Object view1 = integerStack.view();
System.out.println(view1);
}
}
我們來寫一個棧的實際應用
假設表達式中包含三種括號:圓括號、方括號和花括號,並且它們可以任意嵌套。例如{[()]()[{}]}或[{()}([])]等爲正確格式,而{[}()]或[({)]爲不正確的格式。那麼怎麼檢測表達式是否正確呢?
這個問題可以用“期待的急迫程度”這個概念來描述。對表達式中的每一個左括號都期待一個相應的右括號與之匹配,表達式中越遲出現並且沒有得到匹配的左括號期待匹配的程度越高。不是期待出現的右括號則是不正確的。它具有天然的後進先出的特點。
於是我們可以設計算法:算法需要一個棧,在讀入字符的過程中,如果是左括號,則直接入棧,等待相匹配的同類右括號;如果是右括號,且與當前棧頂左括號匹配,則將棧頂左括號出棧,如果不匹配則屬於不合法的情況。另外,如果碰到一個右括號,而堆棧爲空,說明沒有左括號與之匹配,則非法。那麼,當字符讀完的時候,如果是表達式合法,棧應該是空的,如果棧非空,那麼則說明存在左括號沒有相應的右括號與之匹配,也是非法的情況。
public class Match {
private String input;
public Match(String input){
this.input = input;
}
//檢查
public void check() throws Exception{
Stack<Character> stack = new Stack<>(input.length());
for(int i=0;i<input.length();i++){
char str = input.charAt(i);
switch (str) {
case '{':
case '[':
case '(':
stack.push(str);
break;
case '}':
case ']':
case ')':
if(!stack.isEmpty()){
Character pop = (Character) stack.pop();
if((str == '(' && str != ')')|| (str == '[' && str != ']') || (str == '{' && str != '}')){
System.out.println("匹配出錯!字符:"+str+",下標:"+i);
}
}else{
System.out.println("匹配出錯!字符:"+str+",下標:"+i);
}
default:break;
}
}
if(!stack.isEmpty()){
System.out.println("有括號沒有關閉!");
}
}
public static void main(String[] args)throws Exception{
Match match = new Match("我是panda,我們一起學數據結構)");
match.check();
}
}
最後,我們看一下測試的結果