棧和隊列
棧和隊列是兩種特殊的線性表,特殊之處在於插入與刪除操作的位置受到限制,若插入和刪除只能在線性表的一端進行,則爲棧,特點是後進先出(LIFO);若插入和刪除操作分別在線性表的兩端進行,則爲隊列,特點是先進先出(FIFO)。
棧按不同的存儲結構又分爲順序棧和鏈式棧,使用的時候可根據具體情況選擇。當有頻繁的插入刪除操作是選取鏈式存取結構較好。
java中使用棧
1、Stack類
Stack 類表示後進先出(LIFO)的對象堆棧。它通過五個操作對類 Vector 進行了擴展 ,允許將向量視爲堆棧。它提供了通常的 push 和 pop 操作,以及取堆棧頂點的 peek 方法、測試堆棧是否爲空的 empty 方法、在堆棧中查找項並確定到堆棧頂距離的 search 方法。 首次創建堆棧時,它不包含項。Deque 接口及其實現提供了 LIFO 堆棧操作的更完整和更一致的 set,應該優先使用此 set,而非此類
2、Deque接口
一個線性 collection,支持在兩端插入和移除元素。名稱 deque 是“double ended queue(雙端隊列)”的縮寫,通常讀爲“deck”。大多數 Deque 實現對於它們能夠包含的元素數沒有固定限制,但此接口既支持有容量限制的雙端隊列,也支持沒有固定大小限制的雙端隊列。此接口定義在雙端隊列兩端訪問元素的方法。提供插入、移除和檢查元素的方法。每種方法都存在兩種形式:一種形式在操作失敗時拋出異常,另一種形式返回一個特殊值(null 或 false,具體取決於操作)。插入操作的後一種形式是專爲使用有容量限制的 Deque 實現設計的;在大多數實現中,插入操作不能失敗。
在將雙端隊列用作堆棧時,元素被推入雙端隊列的開頭並從雙端隊列開頭彈出。堆棧方法完全等效於 Deque 方法,如下表所示:
操作 | 推展方法 | 等效Deque方法 |
---|---|---|
入棧 | push(e) | addFirst(e) |
出棧 | pop() | removeFirst() |
得到棧頂元素 | peek() | peekFirst() |
Deque實現的子類有ArrayDeque,LinkedList,LinkedBlockingDeque。
- ArrayDeque類
Deque接口的大小可變數組的實現。數組雙端隊列沒有容量限制;它們可根據需要增加以支持使用。它們不是線程安全的;在沒有外部同步時,它們不支持多個線程的併發訪問。禁止 null 元素。此類很可能在用作堆棧時快於 Stack,在用作隊列時快於 LinkedList。 - LinkedList類
此類實現 Deque接口,爲 add、poll 提供先進先出隊列操作,以及其他堆棧和雙端隊列操作。
棧的應用-四則運算
問題:對於一個算術表達式,如1+2*(3-4)+5,假定該表達式以通過編譯系統的語法檢查,怎麼求解該表達式的值。
解題思路:先將中綴表達式轉化爲後綴表達式,然後對後綴表達式進行求解。
中綴表達式:即如題所示的表達式,運算符寫在兩個操作數的中間,由於運算符具有不同的優先級,圓括號會改變運算的次序,使得運算起來比較複雜。
後綴表達式:將運算符卸載兩個操作數之後的表達式。可以嚴格按順序計算,方便運算。如題的表達式轉化爲後綴表達式爲,1 2 3 4 - * + 5 +
實現:
//將中綴表達式轉爲後綴表達式 1+2*(3-4)+5
public static String toPostfix(String expstr){
Deque<String> deque=new ArrayDeque<String>(expstr.length()); //創建運算符棧
String postfix="";//後綴表達式
int i=0;
while(i<expstr.length()){
char ch=expstr.charAt(i);
switch(ch){
case '+':
case '-':
while(!deque.isEmpty() && !deque.getFirst().equals("(")){
postfix+=deque.removeFirst();
}
deque.addFirst(ch+"");
i++;
break;
case '*':
case '/':
while(!deque.isEmpty() && (deque.getFirst().equals("*") || deque.getFirst().equals("/"))){
postfix+=deque.removeFirst();
}
deque.addFirst(ch+"");
i++;
break;
case '(':
deque.addFirst(ch+"");
i++;
break;
case ')':
String out=deque.removeFirst();
while(out!=null && !out.equals("(")){
postfix+=out;
out=deque.removeFirst();
}
i++;break;
default:
while(i<expstr.length() && ch>='0' && ch<='9'){
postfix+=ch;
i++;
if(i<expstr.length())
ch=expstr.charAt(i);
}
postfix+=" ";
}
}
while(!deque.isEmpty()){
postfix+=deque.removeFirst();
}
return postfix;
}
//後綴表達式:1 2 3 4 -*+5 + 計算後綴表達式的值
public static int countValue(String postfix){
Deque<Integer> deque=new LinkedList<Integer>(); //創建操作數棧
int i=0,result=0;
while(i<postfix.length()){
char ch=postfix.charAt(i);
if(ch>='0' && ch<='9'){
result=0;
while(ch!=' '){
result=result*10+Integer.parseInt(ch+"");
i++;
ch=postfix.charAt(i);
}
i++;
deque.addFirst(new Integer(result));
}else{
int y=deque.removeFirst();
int x=deque.removeFirst();
switch(ch){
case '+':result=x+y;break;
case '-':result=x-y;break;
case '*':result=x*y;break;
case '/':result=x/y;break;
}
deque.addFirst(new Integer(result));
i++;
}
}
return deque.removeFirst().intValue();
}