1. 程式人生 > 其它 >演算法練習之括號匹配,棧來解決

演算法練習之括號匹配,棧來解決

技術標籤:演算法

一、問題描述

如何設計一個括號匹配的功能?比如給你一串括號讓你判斷是否符合我們的括號原則,如下所示:

[(){()}{}]符合{}[]{[][[]
[][]{
{}[}}{}}]]] 不符合

二、程式碼解決

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));
		}
	}
}

在這裡插入圖片描述

總結

棧其實就是一個特殊的連結串列或者陣列。
既然棧也是一個線性表,那麼我們肯定會想到陣列和連結串列,而且棧還有這麼多限制,那為什麼我們還要使用這個資料結構呢?

不如直接使用陣列和連結串列來的更直接麼?陣列和連結串列暴露太多的介面,實現上更靈活了,有些技術理解不到位的人員就可能出錯。

所以在某些特定場景下最好是選擇棧這個資料結構。

棧的分類
基於陣列的棧——以陣列為底層資料結構時,通常以陣列頭為棧底,陣列頭到陣列尾為棧頂的生長方向

在這裡插入圖片描述
基於單鏈表的棧——以連結串列為底層的資料結構時,以連結串列頭為棧頂,便於節點的插入與刪除,壓棧產生的新節點將一直出現在連結串列的頭部

在這裡插入圖片描述
最大的區別就是擴容,連結串列天然支援動態擴容。但是可能會棧溢位。