1. 程式人生 > >算法(2) 背包、隊列和棧

算法(2) 背包、隊列和棧

語句 對象 如果 簡單的 應用程序 運算 view end hide

許多基礎數據類型都和對象的集合有關。具體來說,數據類型的值就是一組對象的集合,所有操作都是關於添加、刪除或是訪問集合中的對象。在本節中,我們將學習三種這樣的數據類型,分別是背包(Bag)、隊列(Queue)、和棧(Stack). 他們的不同之處在於刪除或者訪問對象的順序不同。

一、背包

API:

public class Bag<Item> implements Iterable<Item>
Bag()                        創建一個空背包
void add(Item item)            添加一個元素
boolean isEmpty()            背包是否為空
int size() 背包中的元素數量

背包一種不支持從中刪除元素的集合數據類型。叠代的順序不確定且與用例無關。

二、先進先出隊列

在應用程序中使用隊列的主要原因是在用集合保存元素的同時保存它們的相對順序:使他們入列順序和出列順序相同。

API:

public class Queue<Item> implements Iterable<Item>
Queue()                        創建空隊列
void enqueue(Item item)        添加一個元素
Item dequeue()                刪除最近添加的元素
boolean isEmpty() 隊列是否為空 int size() 隊列中的元素數量

三、下壓棧

下壓棧(或簡稱棧)是一種基於後進先出策略的集合類型;當用例使用foreach語句叠代遍歷棧中的元素時,元素的處理順序和它們被壓入的順序正好相反。
在應用程序中使用棧叠代器的一個典型原因是在用集合保存元素的同時顛倒它們的相對順序。

API:

public class Stack<Item> implements Iterable<Item>
Stack()                        創建一個空棧
void push(Item item) 添加一個元素 Item pop() 刪除最近添加的元素 boolean isEmpty() 棧是否為空 int size() 棧中的元素數量

一個棧例子,計算( 1 + ( ( 2 + 3 ) * ( 4 * 5 ) ) )

如何使用程序來完成計算呢?
大神發明了一個非常簡單的算法,用兩個棧(一個用於保存運算符,一個用於保存操作數)完成了這個任務。
表達式由括號、運算符和操作數(數字)組成。我們根據以下4種情況從左到右逐個將這些實體送入棧處理:
.將操作數壓入操作數棧;
.將運算符壓入運算符棧;
.忽略左括號;
.在遇到右括號時,彈出一個運算符,彈出所需數量的操作數,並將運算符和操作數的運算結果壓入操作數棧。(p91)

代碼:

技術分享圖片
package algorithm;

import stdLib.StdIn;
import stdLib.StdOut;

/**
 * 〈Dijkstra的雙棧算術表達式求值算法〉<br>
 */
public class Evaluate {

    public static void main(String[] args) {
        Stack<String> ops = new Stack<>();
        Stack<Double> vals = new Stack<>();
        while (!StdIn.isEmpty()) {
            // 讀取字符,如果是運算符則壓入棧
            String s = StdIn.readString();

            if(s.equals("end")){
                System.out.println(vals.pop());
                break;
            }

            if (s.equals("("))                 ;
            else if (s.equals("+")) ops.push(s);
            else if (s.equals("-")) ops.push(s);
            else if (s.equals("*")) ops.push(s);
            else if (s.equals("/")) ops.push(s);
            else if (s.equals("sqrt")) ops.push(s);
            else if (s.equals(")")){
                //如果字符為")",彈出運算符和操作數,計算結果並壓入棧
                String op = ops.pop();
                double v = vals.pop();
                if(op.equals("+")) v = vals.pop() + v;
                else if(op.equals("-")) v = vals.pop() - v;
                else if(op.equals("*")) v = vals.pop() * v;
                else if(op.equals("/")) v = vals.pop() / v;
                else if(op.equals("sqrt")) v = Math.sqrt(v);
                vals.push(v);
            }//如果字符既非運算符也不是括號,將它作為double值壓入棧
            else vals.push(Double.parseDouble(s));
        }
    }
}
View Code

console輸入計算表達式,輸入end結束:

( 1 + ( ( 2 + 3 ) * ( 4 * 5 ) ) )

end
101.0

算法(2) 背包、隊列和棧