棧的學習-四則運算實例


棧和隊列

棧和隊列是兩種特殊的線性表,特殊之處在於插入與刪除操作的位置受到限制,若插入和刪除只能在線性表的一端進行,則爲棧,特點是後進先出(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。

  1. ArrayDeque類
    Deque接口的大小可變數組的實現。數組雙端隊列沒有容量限制;它們可根據需要增加以支持使用。它們不是線程安全的;在沒有外部同步時,它們不支持多個線程的併發訪問。禁止 null 元素。此類很可能在用作堆棧時快於 Stack,在用作隊列時快於 LinkedList。
  2. 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();
    }

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