演算法練習之括號匹配,棧來解決
阿新 • • 發佈:2020-12-21
技術標籤:演算法
棧
一、問題描述
如何設計一個括號匹配的功能?比如給你一串括號讓你判斷是否符合我們的括號原則,如下所示:
二、程式碼解決
1.構建基礎棧
程式碼如下(示例):
public interface MyStack<Item> {
MyStack<Item> push(Item item); //入棧
Item pop(); //出棧
int size(); // 大小
boolean isEmpty();
}
public class ArrayStack<Item> implements MyStack<Item>{
private Item [] a = (Item[]) new Object[1]; //最好就是開始的時候就設定大小
private int n = 0; //大小 初始的元素個數
public ArrayStack(int cap) {
a = (Item[]) new Object[cap];
}
public MyStack<Item> push(Item item) { //入棧就完成了 //時間複雜度 O(1)
judgeSize();
a[n++] = item;//等於先用n,在對n+1
return null;
}
private void judgeSize(){
if(n >= a.length){ //元素個數已經超出了陣列的個數
resize(2 * a.length); //10*2*2=40個大小了,我出棧了20個了,只剩下20了吧。
}else if(n > 0 && n <= a.length / 2){
resize(a.length / 2);
}
}
private void resize(int size) { //擴容O(n)
Item[] temp = (Item[]) new Object[size];
for(int i = 0 ; i < n; i ++){
temp[i] = a[i];
}
a = temp;
}
public Item pop() { //出棧 O(1)
if(isEmpty()){
return null;
}
Item item = a[--n]; //--n和n-- --n是先把n減了在用,n--先用了在減
a[n] = null;
/*int temp=n-1;
Item item=a[temp];
n--;
a[temp]=null;*/
return item;
}
public int size() {
return n;
}
public boolean isEmpty() {
return n == 0;
}
}
注意一下a[n++] = item
,等於先讓n的位置是item,在對n進行+1
2.用棧的特性來進行匹配
原理:
我們從頭開始遍歷這個算術表示式:
1.遇到是數字 我們就直接入棧到數字棧裡面去。
2.遇到是符合 就把符號棧的棧頂拿出來做比較。如果說他比棧頂符號的優先順序高就直接入棧,如果比符號棧頂的優先順序低或者相同,就從符號棧裡面取棧頂進行計算(從數字棧中取棧頂的2個數),計算完的結果還要再放入到數字棧中。
public class KuoHaoStack {
public static boolean isOk(String s){ //s表示的就是待匹配的括號串 [}使用字元來表示 時間複雜度 O(n)
MyStack<Character> brackets = new ArrayStack<Character>(20);
char c[] = s.toCharArray();
Character top;
for(char x : c){
switch (x) {
case '{':
case '(':
case '[':
brackets.push(x);//O(1)
break;
case '}':
top = brackets.pop();//O(1)
if(top == null) return false;
if(top == '{'){
break;
}else{
return false;
}
case ')':
top = brackets.pop();//O(1)
if(top == null) return false;
if(top == '('){
break;
}else{
return false;
}
case ']':
top = brackets.pop();//O(1)
if(top == null) return false;
if(top == '['){
break;
}else{
return false;
}
default:
break;
}
}
return brackets.isEmpty();
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while(scanner.hasNext()){
String s = scanner.next();
System.out.println("s的匹配結果:"+isOk(s));
}
}
}
總結
棧其實就是一個特殊的連結串列或者陣列。既然棧也是一個線性表,那麼我們肯定會想到陣列和連結串列,而且棧還有這麼多限制,那為什麼我們還要使用這個資料結構呢?
不如直接使用陣列和連結串列來的更直接麼?陣列和連結串列暴露太多的介面,實現上更靈活了,有些技術理解不到位的人員就可能出錯。
所以在某些特定場景下最好是選擇棧這個資料結構。
棧的分類
基於陣列的棧——以陣列為底層資料結構時,通常以陣列頭為棧底,陣列頭到陣列尾為棧頂的生長方向
基於單鏈表的棧——以連結串列為底層的資料結構時,以連結串列頭為棧頂,便於節點的插入與刪除,壓棧產生的新節點將一直出現在連結串列的頭部
最大的區別就是擴容,連結串列天然支援動態擴容。但是可能會棧溢位。