數據結構(棧)

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

}

最後,我們看一下測試的結果

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章