Stack(堆疊) 堆疊的定義 簡單的應用範例 Stack ADT Stack ADT Implementation Based on Array 應用範例 A Mazing Problem Evaluation of Expression
Stack(堆疊) 前述的 list ADT 中,函數: ListInsert (NewItem, Position, Success) ListDelete (Position, Success) 允許我們刪除有效位置 Position 上的資料。函數: ListRetrieve (Position, DataItem, Success) 允許我們取出有效位置 Position 上的資料。
換句話說,ADT list 的資料插入、刪除、和讀取「蠻自由的」 。如果我們取消這樣的自由而限制 只能在資料列固定的某一端插入、刪除、和讀取資料 的話,那麼我們就得到所謂的「堆疊(stack)」抽象資料型 態了。插入和刪除的那一端稱為 top。 66 Top (插入/刪除) 98 資料儲存區 21 18 26 45
Push operation 將資料加入堆疊的動作稱為 push(壓入)。 33 66 66 push 33 98 98 21 21 18 Top 66 Top 66 push 33 98 98 21 21 18 18 26 26 45 45
Pop operation 將資料從堆疊中刪除的動作稱為 pop(彈出)。 66 66 pop 98 98 21 21 18 18 26 Top 66 pop 98 98 Top 21 21 18 18 26 26 45 45
簡單的應用範例 Checking for Balanced Braces Requirements for balanced braces: 1. Each time you encounter a "}", it matches an already encountered "{". 2. When you reach the end of the string, you have matched each "{". abc{defg{ijk}{l{mn}}op}rr abc{def}}{ghij{kl}m
Stack as algorithm executes Input string Stack as algorithm executes {a{b}c} 1. Push '{' 2. Push '{' 3. Pop 4. Pop Stack empty ==> balanced { { { {a{bc} 1. Push '{' 2. Push '{' 3. Pop Stack not empty ==> not balanced { { { {ab}c} 1. Push '{' 2. Pop Stack empty when last '}' ==> not balanced {
解法: while (not at the end of the string) { c = GetNextChar(); if ( c is a '{' ) Push '{' into the stack; else if ( c is a '}' ) { if (Stack is empty) return FALSE; Pop the stack; } return (stack is empty)? TRUE : FALSE;
另解 int counter = 0; while (not at the end of the string) { c = GetNextChar(); if ( the next character is a '{' ) counter++; else if ( the next character is a '}' ) { counter--; if (counter < 0) return false; } return (counter == 0) ? true : false; abc{defg{ijk}{l{mn}}op}rr 1 2 3 abc{def}}{ghij{kl}m 1 -1
Recognizing palindromes A string is called a palindrome if it is the same when reading forward and backward. 為了簡化問題起見,此處我們假設字串中含有單一個 字元 $,此字元區分字串為兩半部,如下圖所示: a b c d e f $ f e d c b a a b c d e f $ f e d k b a X YES NO
作法示範:假定字串為 a b c d e f $ f e d c b a (一)將 $ 之前的字元依序 push 至堆疊中 a b c d e f $ f e d c b a top b a c d e f $ f e d c b a top
(二)碰到 $ 字元 ,捨棄 $ 字元後, 不再 push 其後的字 元至 stack 中,而進 入比較階段。 c b a d e f $ f e d c b a top d c b a e f $ f e d c b a top e d c b a f $ f e d c b a top f e d c b a $ f e d c b a top f e d c b a f e d c b a top (二)碰到 $ 字元 ,捨棄 $ 字元後, 不再 push 其後的字 元至 stack 中,而進 入比較階段。
(三)在這個階段,我們比較 stack 中由上而下的字元和 $ 之後 剩餘的字元,如下所示: f e d c b a f e d c b a top e d c b a e d c b a top d c b a d c b a top c b a c b a top b a b a top a top
則此字串是一個 palindrom,否則不是一個 palindrom。 (四)若比較之後,下列三個條件都成立: (1) 相比的字元一樣; (2) stack 變成空的; (3) 沒有剩餘的字元; 則此字串是一個 palindrom,否則不是一個 palindrom。 a top c b a k b a top c b a top c b a top YES NO NO NO
Stack ADT OBJECTS: a finite list with zero or more elements. FUNCTIONS: Stack Create(max_stack_size) Boolean IsFull(stack, max_stack_size) Boolean IsEmpty(stack) boolean Push (stack, item) boolean Pop (stack) boolean GetTop (stack, top_item)
Stack 又稱為 LIFO ( Last In First Out ): Create (S); Push (S, 1); Push (S, 2); Push (S, 3); Push (S, 4); 1 2 1 3 2 1 4 3 2 1 4 3 2 1 3 2 1 2 1 1 Pop(S);
Stack ADT Implementation Based on Array 靜宜大學資訊管理學系 資料結構講義 2018/11/28 Stack ADT Implementation Based on Array /** ** FILE : StackA.h **/ #define MAX_STACK 100 typedef int itemType; typedef enum {FALSE, TRUE} boolean; typedef struct { int Top; itemType Items[MAX_STACK]; } stack; 1 2 MAX_STACK - 1 k Top Items 蔡奇偉副教授 編製
boolean IsEmpty (stack *S) return (S->Top == -1) TRUE : FALSE; /** ** FILE: StackA.c **/ #include “StackA.h” void Create (stack *S) { S->Top = -1; } boolean IsEmpty (stack *S) return (S->Top == -1) TRUE : FALSE; boolean IsFull (stack *S) return (S->Top >= MAX_STACK-1) TRUE : FALSE; 1 2 MAX_STACK - 1 k Top Items
boolean Push (stack *S, itemType NewItem) { if (IsFull(S)) return FALSE; S->Items[++S->Top] = NewItem; return TRUE; } MAX_STACK - 1 MAX_STACK - 1 Push(&S, 41) k+1 k+1 41 k+1 k 12 k 12 k Top Top 25 2 25 2 36 1 36 1 77 77 Items Items
boolean Pop (stack *S) { if (IsEmpty(S)) return FALSE; --S->Top; return TRUE; } MAX_STACK - 1 MAX_STACK - 1 Pop(&S) k 41 k k 12 k-1 k-1 12 k-1 Top Top 25 2 25 2 36 1 36 1 77 77 Items Items
boolean GetTop (stack *S, itemType *TopItem) { if (IsEmpty(S)) return FALSE; *TopItem = S->Items[S->Top]; return TRUE; } MAX_STACK - 1 GetPop(&S, &TopItem) k 41 k+1 TopItem = 41 12 k Top 25 2 36 1 77 Items
A Mazing Problem 0 1 0 0 0 1 1 0 0 0 1 1 1 1 1 1 0 0 0 1 1 0 1 1 1 0 0 1 1 1 0 1 1 0 0 0 0 1 1 1 1 0 0 1 1 1 1 0 1 1 1 1 0 1 1 0 1 1 0 0 1 1 0 1 0 0 1 0 1 1 1 1 1 1 1 0 0 1 1 0 1 1 1 0 1 0 0 1 0 1 0 1 1 1 1 0 0 1 1 1 1 1 1 1 1 0 0 1 1 0 1 1 0 1 1 1 1 1 0 1 1 1 0 0 0 1 1 0 1 1 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 1 1 1 1 0 0 1 0 0 1 1 1 1 1 0 1 1 1 1 0 0 : open 1 : close N E W NE SE NW SW S
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 1 2 3 4 5 6 7 8 9 10 11 0 1 0 0 0 1 1 0 0 0 1 1 1 1 1 1 0 0 0 1 1 0 1 1 1 0 0 1 1 1 0 1 1 0 0 0 0 1 1 1 1 0 0 1 1 1 1 0 1 1 1 1 0 1 1 0 1 1 0 0 1 1 0 1 0 0 1 0 1 1 1 1 1 1 1 0 0 1 1 0 1 1 1 0 1 0 0 1 0 1 0 1 1 1 1 0 0 1 1 1 1 1 1 1 1 0 0 1 1 0 1 1 0 1 1 1 1 1 0 1 1 1 0 0 0 1 1 0 1 1 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 1 1 1 1 0 0 1 0 0 1 1 1 1 1 0 1 1 1 1 0 1 2 3 4 5 6 7 8 9 1 1 SE row col dir
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 1 2 3 4 5 6 7 8 9 10 11 0 1 0 0 0 1 1 0 0 0 1 1 1 1 1 1 0 0 0 1 1 0 1 1 1 0 0 1 1 1 0 1 1 0 0 0 0 1 1 1 1 0 0 1 1 1 1 0 1 1 1 1 0 1 1 0 1 1 0 0 1 1 0 1 0 0 1 0 1 1 1 1 1 1 1 0 0 1 1 0 1 1 1 0 1 0 0 1 0 1 0 1 1 1 1 0 0 1 1 1 1 1 1 1 1 0 0 1 1 0 1 1 0 1 1 1 1 1 0 1 1 1 0 0 0 1 1 0 1 1 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 1 1 1 1 0 0 1 0 0 1 1 1 1 1 0 1 1 1 1 0 1 2 3 4 5 6 7 8 9 2 2 NE 1 1 SE row col dir
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 1 2 3 4 5 6 7 8 9 10 11 0 1 0 0 0 1 1 0 0 0 1 1 1 1 1 1 0 0 0 1 1 0 1 1 1 0 0 1 1 1 0 1 1 0 0 0 0 1 1 1 1 0 0 1 1 1 1 0 1 1 1 1 0 1 1 0 1 1 0 0 1 1 0 1 0 0 1 0 1 1 1 1 1 1 1 0 0 1 1 0 1 1 1 0 1 0 0 1 0 1 0 1 1 1 1 0 0 1 1 1 1 1 1 1 1 0 0 1 1 0 1 1 0 1 1 1 1 1 0 1 1 1 0 0 0 1 1 0 1 1 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 1 1 1 1 0 0 1 0 0 1 1 1 1 1 0 1 1 1 1 0 1 2 3 4 5 6 7 8 9 1 3 E 2 2 NE 1 1 SE row col dir
靜宜大學資訊管理學系 資料結構講義 2018/11/28 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 1 2 3 4 5 6 7 8 9 10 11 0 1 0 0 0 1 1 0 0 0 1 1 1 1 1 1 0 0 0 1 1 0 1 1 1 0 0 1 1 1 0 1 1 0 0 0 0 1 1 1 1 0 0 1 1 1 1 0 1 1 1 1 0 1 1 0 1 1 0 0 1 1 0 1 0 0 1 0 1 1 1 1 1 1 1 0 0 1 1 0 1 1 1 0 1 0 0 1 0 1 0 1 1 1 1 0 0 1 1 1 1 1 1 1 1 0 0 1 1 0 1 1 0 1 1 1 1 1 0 1 1 1 0 0 0 1 1 0 1 1 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 1 1 1 1 0 0 1 0 0 1 1 1 1 1 0 1 1 1 1 0 1 2 3 4 5 6 7 8 9 1 4 E 1 3 E 2 2 NE 1 1 SE row col dir 蔡奇偉副教授 編製
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 1 2 3 4 5 6 7 8 9 10 11 0 1 0 0 0 1 1 0 0 0 1 1 1 1 1 1 0 0 0 1 1 0 1 1 1 0 0 1 1 1 0 1 1 0 0 0 0 1 1 1 1 0 0 1 1 1 1 0 1 1 1 1 0 1 1 0 1 1 0 0 1 1 0 1 0 0 1 0 1 1 1 1 1 1 1 0 0 1 1 0 1 1 1 0 1 0 0 1 0 1 0 1 1 1 1 0 0 1 1 1 1 1 1 1 1 0 0 1 1 0 1 1 0 1 1 1 1 1 0 1 1 1 0 0 0 1 1 0 1 1 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 1 1 1 1 0 0 1 0 0 1 1 1 1 1 0 1 1 1 1 0 1 2 3 4 5 6 7 8 9 1 5 SW 1 4 E 1 3 E 2 2 NE 1 1 SE row col dir
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 1 2 3 4 5 6 7 8 9 10 11 0 1 0 0 0 1 1 0 0 0 1 1 1 1 1 1 0 0 0 1 1 0 1 1 1 0 0 1 1 1 0 1 1 0 0 0 0 1 1 1 1 0 0 1 1 1 1 0 1 1 1 1 0 1 1 0 1 1 0 0 1 1 0 1 0 0 1 0 1 1 1 1 1 1 1 0 0 1 1 0 1 1 1 0 1 0 0 1 0 1 0 1 1 1 1 0 0 1 1 1 1 1 1 1 1 0 0 1 1 0 1 1 0 1 1 1 1 1 0 1 1 1 0 0 0 1 1 0 1 1 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 1 1 1 1 0 0 1 0 0 1 1 1 1 1 0 1 1 1 1 0 1 2 3 4 5 6 7 8 9 2 4 SE 1 5 SW 1 4 E 1 3 E 2 2 NE 1 1 SE row col dir
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 1 2 3 4 5 6 7 8 9 10 11 0 1 0 0 0 1 1 0 0 0 1 1 1 1 1 1 0 0 0 1 1 0 1 1 1 0 0 1 1 1 0 1 1 0 0 0 0 1 1 1 1 0 0 1 1 1 1 0 1 1 1 1 0 1 1 0 1 1 0 0 1 1 0 1 0 0 1 0 1 1 1 1 1 1 1 0 0 1 1 0 1 1 1 0 1 0 0 1 0 1 0 1 1 1 1 0 0 1 1 1 1 1 1 1 1 0 0 1 1 0 1 1 0 1 1 1 1 1 0 1 1 1 0 0 0 1 1 0 1 1 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 1 1 1 1 0 0 1 0 0 1 1 1 1 1 0 1 1 1 1 0 4 14 E 17 3 13 SE 16 3 12 E 15 1 4 E 3 1 3 E 2 2 2 NE 1 1 1 SE row col dir
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 1 2 3 4 5 6 7 8 9 10 11 0 1 0 0 0 1 1 0 0 0 1 1 1 1 1 1 0 0 0 1 1 0 1 1 1 0 0 1 1 1 0 1 1 0 0 0 0 1 1 1 1 0 0 1 1 1 1 0 1 1 1 1 0 1 1 0 1 1 0 0 1 1 0 1 0 0 1 0 1 1 1 1 1 1 1 0 0 1 1 0 1 1 1 0 1 0 0 1 0 1 0 1 1 1 1 0 0 1 1 1 1 1 1 1 1 0 0 1 1 0 1 1 0 1 1 1 1 1 0 1 1 1 0 0 0 1 1 0 1 1 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 1 1 1 1 0 0 1 0 0 1 1 1 1 1 0 1 1 1 1 0 4 14 E 17 3 13 SE 16 3 12 E 15 1 4 E 3 1 3 E 2 2 2 E 1 1 1 SE Backtracking row col dir
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 1 2 3 4 5 6 7 8 9 10 11 0 1 0 0 0 1 1 0 0 0 1 1 1 1 1 1 0 0 0 1 1 0 1 1 1 0 0 1 1 1 0 1 1 0 0 0 0 1 1 1 1 0 0 1 1 1 1 0 1 1 1 1 0 1 1 0 1 1 0 0 1 1 0 1 0 0 1 0 1 1 1 1 1 1 1 0 0 1 1 0 1 1 1 0 1 0 0 1 0 1 0 1 1 1 1 0 0 1 1 1 1 1 1 1 1 0 0 1 1 0 1 1 0 1 1 1 1 1 0 1 1 1 0 0 0 1 1 0 1 1 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 1 1 1 1 0 0 1 0 0 1 1 1 1 1 0 1 1 1 1 0 3 13 SE 16 3 12 E 15 1 4 E 3 1 3 E 2 2 2 E 1 1 1 SE Backtracking row col dir
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 1 2 3 4 5 6 7 8 9 10 11 0 1 0 0 0 1 1 0 0 0 1 1 1 1 1 1 0 0 0 1 1 0 1 1 1 0 0 1 1 1 0 1 1 0 0 0 0 1 1 1 1 0 0 1 1 1 1 0 1 1 1 1 0 1 1 0 1 1 0 0 1 1 0 1 0 0 1 0 1 1 1 1 1 1 1 0 0 1 1 0 1 1 1 0 1 0 0 1 0 1 0 1 1 1 1 0 0 1 1 1 1 1 1 1 1 0 0 1 1 0 1 1 0 1 1 1 1 1 0 1 1 1 0 0 0 1 1 0 1 1 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 1 1 1 1 0 0 1 0 0 1 1 1 1 1 0 1 1 1 1 0 3 6 NE 9 3 5 E 8 1 4 E 3 1 3 E 2 2 2 E 1 1 1 SE Backtracking row col dir
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 1 2 3 4 5 6 7 8 9 10 11 0 1 0 0 0 1 1 0 0 0 1 1 1 1 1 1 0 0 0 1 1 0 1 1 1 0 0 1 1 1 0 1 1 0 0 0 0 1 1 1 1 0 0 1 1 1 1 0 1 1 1 1 0 1 1 0 1 1 0 0 1 1 0 1 0 0 1 0 1 1 1 1 1 1 1 0 0 1 1 0 1 1 1 0 1 0 0 1 0 1 0 1 1 1 1 0 0 1 1 1 1 1 1 1 1 0 0 1 1 0 1 1 0 1 1 1 1 1 0 1 1 1 0 0 0 1 1 0 1 1 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 1 1 1 1 0 0 1 0 0 1 1 1 1 1 0 1 1 1 1 0 3 6 E 9 3 5 E 8 1 4 E 3 1 3 E 2 2 2 E 1 1 1 SE row col dir
代數運算 Infix, Postfix, and Prefix Expressions Evaluation of Postfix Expressions Conversion from Infix to Postfix Expressions
從小我們就熟悉計算式 a+b 表示 「a 加上 b」,也知道「先乘除 後加減」這個口訣,所以 a+b*c 這個式子表示「 a 加上 b 乘 c 的 結果」 而不是「a 加 b以後再乘以 c」— 後者必須用括號寫為 ( a+b )*c。像 a+b 這樣的計算式寫法,我們稱之為中置算式 (infix expression),所以這樣稱呼,原因是運算子 + 擺在兩個 運算元 a 和 b 之間。 有沒有必要一定這樣寫呢?譬如:我們是否 可以將同樣的算式寫成 前置算式(prefix expression) + a b 或者後置算式(postfix expression) a b + 呢?雖然這兩種寫法看起來「怪怪的」,但是在電腦科學的領域 中卻常常會看到類似的寫法。
前置算式 + a b 可以看成 + (a, b) 而解讀為:「+ 代表 解釋任何 C 的函數: func (p1, p2, ..., pk) 都是前置算式,其中 func 是運算子,而參數 p1, p2, ..., pk 為其運算元。許多的函數型的程式語言,如 ML 和 LISP 等等,就是採用這樣的「函數即為運算子」 的觀點,如此一來,使得該類型程式語言的語法變 得簡鍊許多。 堆疊可以用於很有效率地計算後置算式。這個技巧用 於一些程式語言,如 FORTH 和用於雷射印表機的 Postscript。
計算後置算式 2 * ( 3 + 4 ) = 14 2 * 3 + 4 = 10 A - ( B / C * D ) 2 3 4 + * 2 * 3 + 4 = 10 A - ( B / C * D ) 2 3 4 + * 2 3 * 4 + A B C / D * - 7 6 10 A - ( B / C * D ) B / C B / C * D 14
2 * ( 3 + 4 ) = 14 2 3 4 + * 2 3 4 + * 4 + * 3 2 * 7 2 7 14 3 4 + * 2 + * 4 3 2 14
2 * 3 + 4 = 10 2 3 * 4 + 6 10 2 3 * 4 + * 4 + 3 2 + 4 6 3 * 4 + 2 4 + 6 10
Algorithm for calculating postfix expression Assumptions: The input string is a syntactically correct postfix expression. No unary operators are present. No exponentiation operators are present. Operands are single uppercase letters that represent integer values. A B C / D * - 【範例】
for (each character Ch in the string) { if (Ch is an operator named Op) { /* evaluate and push the result */ Operand2 = top of the stack Pop the stack Operand1 = top of the stack Result = Operand1 Op Operand2 Push Result onto stack } else /* Ch is an operand */ Push Ch onto stack
中置算式轉換為後置算式 從前面的例子,我們知道利用堆疊可以很容易地計算 後置算式。因此,計算中置算式可以分為底下的兩個 步驟來執行: 1. 將中置算式轉換為後置算式 2. 用堆疊來計算所得的後置算式
【範例】 2 * 3 + 4 = 10 2 3 * 4 + 6 10 2 * ( 3 + 4 ) = 14 2 3 4 + * 7 14
【範例】
Observations: 運算元的次序在中置算式和後置算式是完全相同的。 在中置算式中,如果運算元 X 在運算子 Op 之前, 那麼,在後置算式中,運算元 X 也會在運算子 Op 之前。 所有括號在轉換後均被消除。 運算子在後置算式中的出現順序是依照其在中置算式 的運算順序而定。
中置算式的運算法則 括號內算式先做 先乘除後加減 由左至右運算 A - ( B + C * D ) / E Þ ( A - ( ( B + ( C * D ) ) / E ) ) Þ ( A - ( ( B + C D *) / E ) ) Þ ( A - ( B C D * + / E ) ) Þ ( A - B C D * + E / ) Þ A B C D * + E / - A - B + C * D / E Þ ( ( A - B ) + ( ( C * D ) / E ) ) Þ ( A B - + ( ( C * D ) / E ) ) Þ ( A B - + ( C D * / E ) ) Þ ( A B - + C D * E / ) Þ A B - C D * E / +
中置算式轉換為後置算式的演算法 1. 當碰到運算元時,將其直接加附於輸出字串之後。 2. 當碰到左括號時,將其 push 至堆疊中。 3. 當碰到右括號時,將堆疊中的運算子 pop 出來並加 附於輸出字串之後直到碰到左括號為止,然後再將 此左括號 pop 掉。
4. 當碰到運算子時,若此時堆疊是空的,則直接將此 運算子加附於輸出字串之後;否則,將堆疊中運算 優先次序較高或相同的運算子 pop 出來並加附於輸 出字串之後直到下列條件成立為止 (i) 碰到左括號 (ii) 碰到優先次序較低的運算子 (iii) 堆疊變為空 然後將此輸入運算子 push 至堆疊中。 5. 當輸入字串全部處理完時,將堆疊中所剩餘的運算 子逐一地 pop 出來並加附於輸出字串之後直到堆疊 變為空為止。
Algorithm for ( each character ch in the infix expression ) { switch ( Ch ) { case operand : PE = PE‧Ch; break; case ‘(‘ : S.Push ( Ch, Success); break; case ‘)’ : while ( top of S is not ‘(‘ ) { pop down to the matching open ( PE = PE‧( top of S ); S.Pop (Success ); } S.Pop ( Success ); remove the open ( break; case operator: PE‧Ch : PE concatenate Ch
while ( !S.StackIsEmpty () and ( top of S is not ‘(‘ ) and 靜宜大學資訊管理學系 資料結構講義 2018/11/28 while ( !S.StackIsEmpty () and ( top of S is not ‘(‘ ) and ( Precedence ( top of S ) >= Precedence ( Ch ) ) { PE = PE‧( top of S ); S.Pop (Success ); } S.Push ( Ch, Success); while ( !S.StackIsEmpty () ) { add the remaining operators in the stack 蔡奇偉副教授 編製
【範例】 A - ( B + C * D ) / E A B C D * + E / - A A 1 - - A 4 ( - ( A 2 Ch Stack S ( bottom to top) PE rule A A 1 - - A 4 ( - ( A 2 B - ( A B 1 + - ( + A B 4 C - ( + A B C 1 * - ( + * A B C 4 D - ( + * A B C D 1
) - ( + A B C D * 3 - ( A B C D * + 3 - A B C D * + 3 / - / A B C D * + 4 E - / A B C D * + E 1 - A B C D * + E / 5 A B C D * + E / - 5