Validate test and pseudocode.
I. validate test
At the first, a table and some principles for ADT will be defined.
Token State sign
PLUS, MULT, DIV a
Operand b
LPAR c
RPAR d
MINUS e
1. The arithmetic expression must start with operand, MINUS, or LPAR (b, e, and c).
2. The arithmetic expression must finish with operand, or RPAR (b and d).
3. Every successive two tokens must satisfy:
ab, ac, ba, bd, cb, da, be, ce, de, eb, ec, cc, dd.(e.g. ce mean LPAR and MINUS can be successive, ¡®ba¡¯ mean a operand and PLUS can border upon).
4. The number of LPARs and RPARs must be same, that mean the number of c and d must be same.
5. If a LPAR appear, a RPAR must appear after (That mean, if c appears, d must be after c).
If the expression is not valid an InvalidExpressionException is thrown and the whole process is terminated.
Now, there are four examples will show how the validate test works.
There is an arithmetic expression ( (7 * ( 23 ¨C 105 / 15 ) )- 19 )
That is,
( ( 7 * ( 23 - 105 / 15 ) ) - 19 )
Now from the 1st element transfer the token to state number, and put them into a queue called Q
c c b a c b e b a b d d e b d
From Q, we can know that,
1. This expression starts with operand (state number is b).
2. This expression finishes with operand (state number is b).
3. Every successive two tokens are satisfied (cc, cb, ba, ac, cb, be, eb, ba, ab, bd, dd, de, eb and bd).
4. These are three LPARs and three RPARs. In other word, there is three c and three d.
5. LPAR is in front of RPAR. In other word, c is in front of d.
So this is a valid arithmetic expression.
There is an arithmetic expression ¨C 9 * ( 23 ¨C 105 / 15 ) - ( - 15 + 1 )
That is,
- 9 * ( 23 - 105 / 15 ) - ( - 15 + 1 )
Now from the 1st element transfer the token to state number, and put them into a queue called Q
e b a c b e b a b d e c e b a b d
From Q, we can know that,
1. This expression starts with MINUS (state number is e).
2. This expression finishes with RPAR (state number is d).
3. Every successive two tokens are satisfied (eb, ba, ac, cb, be, eb, ba, ab, bd, de, ec, ce, eb, ba, ab, and bd).
4. There are two LPARs and Two RPARs.
5. LPARs always have a RPAR after themselves.
So this arithmetic expression is valid.
There is an arithmetic expression 7 * ( 23 ¨C 105 / 15- ) 19
That is,
7 * ( 23 - 105 / 15 - ) 19
Now from the 1st element transfer the token to state number, and put them into a queue called Q
b a c b e b a b e d b
From Q, we can know that,
1. This expression starts with operand (state number is b).
2. This expression finishes with operand (state number is b).
3. ed and db are not satisfied.
So, this arithmetic expression is not valid.
These is an arithmetic expression 9 * 7 ) + ( 8 ¨C 5) * ( 6
That is,
9 * 7 ) + ( 8 - 5 ) * ( 6
Now from the 1st element transfer the token to state number, and put them into a queue called Q
b a b d a c b e b d a c b
From Q, we can know that,
1. This expression starts with operand (state sign is b).
2. This expression finishes with operand (state sign is b).
3. Every successive two tokens are satisfied (ba, ab, bd, da, ac, cb, be, eb, bd, da, ac, cb).
4. There are two LPARs and two RPARs. (Two e and two d).
5. There is not RPAR after the second LPAR.
So this arithmetic expression is not valid.
After validation, the result is below:
( (7 * ( 23 ¨C 105 / 15 ) )¨C 19) ¡¡¡¡¡¡¡¡¡....Valid
¨C 9 * ( 23 ¨C 105 / 15 ) - ( - 15 + 1 ) ...............................Valid
7 * ( 23 ¨C 105 / 15- ) 19 .............................................Invalid
9 * 7 ) + ( 8 ¨C 5) * ( 6 .................................................Invalid
II. Validate test pseudocode
Algorithm validate_start_element(EL):
Input: a state sign from Q
Output: boolean value that indicates whether the EL is valid
if EL<>;b or EL<>;e or EL<>;c then
throw an InvalidExpressionException
Algorithm validate_finish_element(EL):
Input: a state sign from Q
Output: boolean value that indicates whether the EL is valid
if EL<>;b or EL<>;d then
throw an InvalidExpressionException
Algorithm validate_successive_two_elements(EL1, EL2):
Input: successive two state signs EL1 and EL2 from Q
Output: boolean value that indicates whether the EL is valid
EL ß EL1 + EL2
if EL<>;ab or EL<>;ac or EL<>;ba or EL<>;bd or EL<>;cb or EL<>;da or EL<>;be or EL<>;ce or EL<>;de or EL<>;eb or EL<>;ec or EL<>;cc or EL<>;dd then
throw an InvalideExpressionException
Algorithm validate_place_LPAR_RPAR( ):
Input: a state s and an integer r
Output: boolean value that indicates whether the expression is valid
if !PAR.stack_isEmpty( ) then
throw an InvalidExpressionException
Algorithm element_transfer_state_sign(EL):
Input: an element EL of the expression
Output: a state sign
if EL = ¡®*¡¯ or EL = ¡®+¡¯ or EL = ¡®/¡¯ then
return ¡®a¡¯
else if EL = ¡®(¡¯ then
return ¡®c¡¯
else if EL = ¡®)¡¯ then
return ¡®d¡¯
else if EL = ¡®-¡¯ then
return ¡®e¡¯
else return ¡®b¡¯
Algorithm enqueue(o):
Input: an object o insert queue
Output: None
if queue_size( ) = N-1 then
throw a QueueFullException
Q[r] ß o
r ß (r+1) mod N
Algorithm dequeue( ):
Input: None
Output: Object from queue
if queue_isEmpty( ) then
throw a QueueemptyException
temp ß Q[f]
Q[f] ß null
f ß (f+1) mod N
return temp
Algorithm queue_isEmpty( ):
Input: None
Output: Boolean
return(f = r)
Algorithm queue_size( ):
Input: None
Output: Integer
return (N ¨C f + r) mod N
Algorithm NumberOfElements(ep):
Input: an expression
Output: a integer of the number of elements
return ep.length
Algorithm: stack_clear( )
Input: none
Output: none
while (! stack_isEmpty( )) do
pop ( )
Algorithm: queue_clear( )
Input: none
Output: none
while (! queue_isEmpty( )) do
dequeue( )
Algorithm: stack_isEmpty( )
Input: none
Output: boolean
return (t<0)
Algorithm: push(o)
Input: Object
Output: None
if stack_size( )=N then
throw a StackFullException
t ß t + 1
S[t] ß o
Algorithm: pop( )
Input: None
Output: Obejct
if stack_isEmpty( ) then
throw a StackEmptyException
return S[t]
Algorithm validate_test(expression &EP): // Arithmetic expression validate test
Input: an expression EP
Output: boolean value that indicates whether the expression is valid
element EL //EL is an element of expression
int n ß NumberOfElements(EP) // n is the number of elements
queue Q // A queue store state sign
stack PAR // A stack that use to validate LPAR and RPAR
char S, T ß null // S and T are state signs
Q.queue_clear( ) // clear queue Q
PAR.queue_clear ( ) // clear stack PAR
int r ß 0 // state of method valid_place_LPAR_RPAR( ) just two states 1 or 0
for i ß 0 to n-1 do
EL ß EP.getElement(i) // get out the element of No.i
S ß element_transfer_state_sign(EL) // transfer the EL to state sign
Q.enqueue (S)
S ß null
for i ß 1 to n do // start validate test
if i = 1 then
S ß Q.dequeue( )
validate_start_element(S)
if S = c then
PAR.push(c)
if i >; 1 and i < n then
T ß Q.dequeue( )
validate_successive_two_elements(S, T)
if T = c then
PAR.push(c)
if T = d then
PAR.pop( )
S ß T
if i = n then
T ß Q.dequeue( )
validate_successive_two_elements(S, T)
validate_finish_element(T)
if T = c then
PAR.push(c)
if T = d then
PAR.pop( )
validate_place_LPAR_RPAR()
return (valid expression)
Infix2postfix test and pseudocode
I. Infix2postfix test
The rules of infix transfer to postfix:
1. ¡®#¡¯ mean minus, this is a operator, it just need one operand, if a expression is #5, this mean #5 = -5
e.g. some expression like 7*(-5+6)/(-7), it should be transferred to 7*(#5+6)/(#7)
2. Take the tokens from left to right.
3. If the input token be for an operand, it is enqueued to the output buffer q3.
4. If the input token be for a LPAR, it is pushed onto the stack.
5. If the input token be for a RPAR, tokens are popped from the stack and enqueued to the output until the first LPAR token be popped. The popped LPAR token and the input RPAR token are both discarded.
6. If the input token be for an operator the action depends upon its precedence relative to that on top of the stack.
l If the precedence of the input token is greater than the of the token on top of the stack ¨C of if the stack be empty of if the top be a LPAR token ¨C the input token is pushed onto the stack.
l Otherwise the stack is popped and the popped token is enqueued to the output and then the input token is pushed onto the stack.
7. At end of input tokens are popped from the stack and enqueued to the output until the stack become empty.
8. The RPAR never be pushed onto stack.
The operator Precedence:
The operators MULT and DIV (usually coded as * and / ) have higher precedence than those for PLUS and MINUS (usually coded as + and - ).
Token In-Stack Precedence (ISP) In-Coming Precedence (ICP)
( -1 6
) 0 0
+ 2 2
- 2 2
* 3 3
/ 3 3
# (-) 4 5
operand 0 0
Figure: The precedence of tokens
Figure: Infix transfer to postfix flow chart
Infix2postfix test data
It will give out 2 examples for infix transfer to postfix.
A. 7 * (#5 + 6) / (#7)
Step Token Postfix Stack
1 7 7
2 * 7 *
3 ( 7 *, (
4 # 7 *, (, #
5 5 7 5 *, (, #
6 + 7 5 # *, (, +
7 6 7 5 # 6 *, (, +
8 ) 7 5 # 6 + *
9 / 7 5 # 6 + * /
10 ( 7 5 # 6 + * /, (
11 # 7 5 # 6 + * /, (, #
12 7 7 5 # 6 + * 7 /, (, #
13 ) 7 5 # 6 + * 7 # /
So, the postfix expression is 7 5 # 6 + * 7 # /
B. ( 3 * 3 ¨C 4 * 5 * 8 ) / ( 2 * 6 )
Step Token Postfix Stack
1 ( (
2 3 3 (
3 * 3 (, *
4 3 3 3 (, *
5 - 3 3 * (, -
6 4 3 3 * 4 (, -
7 * 3 3 * 4 (, -, *
8 5 3 3 * 4 5 (, -, *
9 * 3 3 * 4 5 * (, -, *
10 8 3 3 * 4 5 * 8 (, -, *
11 ) 3 3 * 4 5 * 8 * -
12 / 3 3 * 4 5 * 8 * - /
13 ( 3 3 * 4 5 * 8 * - /, (
14 2 3 3 * 4 5 * 8 * - 2 /, (
15 * 3 3 * 4 5 * 8 * - 2 /, (, *
16 6 3 3 * 4 5 * 8 * - 2 6 /, (, *
17 ) 3 3 * 4 5 * 8 * - 2 6 * /
So, the postfix expression is 3 3 * 4 5 * 8 * - 2 6 * /
II. Infix2postfix pseudocode
Algorithm: dequeue( )
Input: None
Output: Object
if queue_isEmpty( ) then
throw a QueueEmptyException
return Q[f]
Algorithm: queue_size( )
Input: None
Output: Integer
return (N-f+r) mod N
Algorithm: push(o)
Input: Object
Output: None
if stack_size( )=N then
throw a StackFullException
t ß t + 1
S[t] ß o
Algorithm: pop( )
Input: None
Output: Obejct
if stack_isEmpty( ) then
throw a StackEmptyException
return S[t]
Algorithm: stack_isEmpty( )
Input: none
Output: boolean
return (t<0)
Algorithm: enqueued (o)
Input: Object
Output: None
if queue_size( ) = N ¨C 1 then
throw a QueueFullException
Q[r] ß o
r ß (r+1) mod N
Algorithm: stack_size( )
Input: None
Output: integer
return t+1
Algorithm: stack_clear( )
Input: none
Output: none
while(! stack_isEmpty( )) do
pop ( )
Algorithm: queue_clear( )
Input: none
Output: none
while(! queue_isEmpty( )) do
dequeue( )
Algorithm: isOperand(o)
Input: an object
Output: Boolean
return ( o <>; ¡®+¡¯ or o <>; ¡®-¡¯ or o <>; ¡®*¡¯ or o <>; ¡®/¡¯ or o <>; ¡®(¡¯ or o <>; ¡®)¡¯ or o<>; ¡®#¡¯)
Algorithm: isRPAR(o)
Input: an object
Output: Boolean
return ( o = ¡®)¡¯ )
Algorithm: isLPAR(o)
Input: an object
Output: Boolean
return ( o = ¡®(¡¯ )
Algorithm: top( )
Input: none
Output: object
if stack_isEmpty then
throw a StackEmptyException
else
return Q[t]
Algorithm: ISP(o)
Input: object
Output: integer
if o = ¡®(¡¯ then
return -1
if o = ¡®)¡¯ then
return 0
if o = ¡®+¡¯ or o = ¡®-¡¯ then
return 2
if o = ¡®*¡¯ or o = ¡®/¡¯ then
return 3
if o = ¡®#¡¯ then
return 4
Algorithm: ICP(o)
Input: object
Output: integer
if o = ¡®(¡¯ then
return 6
if o = ¡®)¡¯ then
return 0
if o = ¡®+¡¯ or o = ¡®-¡¯ then
return 2
if o = ¡®*¡¯ or o = ¡®/¡¯ then
return 3
if o = ¡®#¡¯ then
return 5
Algorithm: infix_transfer (Q1)
Input: one queue
Output: Q2
A ß Q1.dequeue( )
if Q1 = ¡®-¡¯ then
Q2.enqueue(¡®#¡¯)
else
Q2.enqueue(A)
while (!Q1.queue_isEmpty( )) do
B ß Q1.dequeue( )
if A+B <>; ¡®LPAR¡¯ + ¡®-¡¯ then
Q2.enqueue(B)
else
Q2.enqueue(¡®#¡¯)
A ß B
return Q2
Algorithm: infix2postfix (infix &INfix)
Input: an infix expression INfix, INfix is a queue.
Output: a postfix expression PO, PO is a queue
element EL
stack ST
queue PO
queue IN
int n ß INfix.queue_size( )
ST.stack_clear( )
PO.queue_clear( )
IN ß infix_transfer (INfix)
for i ß 1 to n do
EL ß IN.dequeue( )
if isOperand(EL) then // if EL is a operand
PO. enqueue(EL) // put EL into queue PO
continue
if ST.stack_isEmpty( ) then // if ST is empty
ST.push(EL) // push the EL onto stack ST
continue
if isRPAR(EL) then
while (!(ST.stack_isEmpty( ) or isLPAR(ST.top( ))) do
EL = ST.pop( )
PO.enqueue(EL) // take out operator from ST and enqueued PO before LPAR
ST.pop( ) // pop LPAR and discard
continue
if ISP(ST.top( )) < ICP(EL) then
ST.push(EL)
else
while (!(ST.stack_isEmpty( ) or ISP(ST.top( )) < ICP(EL))) do
PO.enqueue(ST.pop( ))
ST.push(EL)
while (!ST.stack_isEmpty()) do
PO.enqueue(ST.pop( ))
return PO
Evaluate test and pseudocode
I. Evaluate test
u If the token is for a number, the number is pushed onto the stack.
u If the token is for an operator which needs two operands, the top two numbers are popped from the stack, the operation is performed upon those two numbers and the result pushed back onto the stack.
u If the token is for an operator which needs just one operand, the top number are popped from the stack, the operation is performed with this number and the result pushed back onto the stack.
It will give out 2 examples for evaluating test, ¡®4 4 * 9 4 * 6 * - 2 1 * /¡¯ and ¡®7 5 # 6 + * 7 # /¡¯
A. 4 3 * 9 4 * 6 / - 2 1 * /
Token Operand 1 Operand 2 Value Stack
4 4
3 4, 3
* 4 3 12 12
9 4 3 12 12, 9
4 4 3 12 12, 9, 4
* 9 4 36 12, 36
6 9 4 36 12, 36, 6
/ 36 6 6 12, 6
- 12 6 6 6
2 12 6 6 6, 2
1 12 6 6 6, 2, 1
* 2 1 2 6, 2
/ 6 2 3 3
So, the result is 3.
B. 7 5 # 6 + * 7 # /
Token Operand 1 Operand 2 Value Stack
7 7
5 7, 5
# 5 -5 7, -5
6 5 -5 7, -5, 6
+ -5 6 1 7, 1
* 7 1 7 7
7 7 1 7 7, 7
# 7 1 -7 7, -7
/ 7 -7 -1 -1
So, the result is -1.
II. Evaluate pseudocode
Algorithm: dequeue( )
Input: None
Output: Object
if isEmpty( ) then
throw a QueueEmptyException
return Q[f]
Algorithm: queue_size( )
Input: None
Output: Integer
return (N-f+r) mod N
Algorithm: stack_size( )
Input: None
Output: integer
return t+1
Algorithm: push(o)
Input: Object
Output: None
if stack_size( )=N then
throw a StackFullException
t ß t + 1
S[t] ß o
Algorithm: pop( )
Input: None
Output: Object
if stack_isEmpty( ) then
throw a StackEmptyException
return S[t]
Algorithm: queue_isEmpty( )
Input: none
Output: boolean
return(f=r)
Algorithm: stack_isEmpty( )
Input: none
Output: boolean
return (t<0)
Algorithm: stack_clear( )
Input: none
Output: none
while(! stack_isEmpty( )) do
pop ( )
Algorithm: calculate(EL, y, x)
Input: EL is an operator, y and x are operand
Output: return value of y EL x
if EL = ¡®+¡¯ then
return y+x
if EL = ¡®-¡¯ then
return y-x
if EL = ¡®*¡¯ then
return y*x
if EL = ¡®/¡¯ then
return y/x
if EL = ¡®#¡¯ then
return 0 - y
Algorithm evaluate (postfix &PO)
Input: a postfix expression PO, PO is a queue.
Output: a result of expression PO
element EL
double x, y, r ß 0
stack ST
int n ß PO.queue_size( )
ST.stack_clear( )
for i ß 1 to n do
EL = PO.dequeue( )
if EL<>; ¡®+¡¯ or EL<>; ¡®-¡¯ or EL<>; ¡®*¡¯ or EL<>; ¡®/¡¯ or EL<>;¡®#¡¯ then
ST.push(EL)
else
if EL = ¡®#¡¯ then
x ß ST.pop( )
y ß 0
r ß calculate (EL, y, x)
ST.push(r)
else
x ß ST.pop( )
y ß ST.pop( )
r ß calculate(EL, y, x)
ST.push(r)
if PO.queue_isEmpty( ) then
return ST.pop( )
else
return 0
lilu_0608 »Ø¸´ÓÚ£º2004-12-14 06:47:14
ÓÐЩ±í¸ñÎÞ·¨Õý³£ÏÔʾ£¬Çë¼ûÁ¡£
|