栈的一个应用—关于中缀和后缀表达式求值
中缀表达式直接转化为后缀表达式求值:
import java. util. Stack;
public class Suffix {
static Stack< Character> op = new Stack < > ( ) ;
public static String tosuffix ( String str) {
char [ ] str1= str. toCharArray ( ) ;
int len= str1. length;
String res= "" ;
for ( int i= 0 ; i< len; i++ ) {
char ch= str1[ i] ;
if ( ch== ' ' ) { continue ; }
if ( ch>= '0' && ch<= '9' ) {
res= res+ ch;
continue ;
}
if ( ch== '(' ) {
op. push ( ch) ;
}
if ( ch== '+' || ch== '-' ) {
while ( ! op. isEmpty ( ) && op. peek ( ) != '(' ) {
res+= op. pop ( ) ; }
op. push ( ch) ;
continue ;
}
if ( ch== '*' || ch== '/' ) {
while ( ! op. isEmpty ( ) && ( op. peek ( ) == '*' || op. peek ( ) == '/' ) ) { res= res+ op. pop ( ) ; }
op. push ( ch) ;
continue ;
}
if ( ch== ')' ) {
while ( ! op. isEmpty ( ) && op. peek ( ) != '(' ) {
res+= op. pop ( ) ;
}
op. pop ( ) ;
continue ;
}
}
while ( ! op. empty ( ) ) { res+= op. pop ( ) ; }
return res;
}
public static Float getValue ( String str) {
Stack< Float> v = new Stack < > ( ) ;
char [ ] arr = str. toCharArray ( ) ;
int len = arr. length;
for ( int i = 0 ; i < len; i++ ) {
Character ch = arr[ i] ;
if ( ch >= '0' && ch <= '9' )
v. push ( Float. valueOf ( ch - '0' ) ) ;
else v. push ( caculate ( ch, v. pop ( ) , v. pop ( ) ) ) ; }
return v. pop ( ) ;
}
public static Float caculate ( char op, Float num1, Float num2) {
switch ( op) {
case '+' :
return num1+ num2;
case '-' :
return num2- num1;
case '/' :
return num2/ num1;
case '*' :
return num2* num1;
default : return Float. valueOf ( 0 ) ;
}
}
public static void main ( String[ ] args) {
String str= "5+4*3" ;
System. out. println ( getValue ( tosuffix ( str) ) ) ;
}
}
注:数字只能选择0-9之间的数字,而不能选择其他数字。
要想更进一步输入双位数,则可以将数组的下一位也在同一步中进行判断,然后删除下一个数组的对应 元素,使得单一位存储双数个,而数组也将改为string类型。
实现(先转化为数组,然后,在):
private static String[ ] strToExpressionArr ( String str) {
ArrayList< String> list = new ArrayList < > ( ) ;
for ( int i = 0 ; i < str. length ( ) ; i++ ) {
if ( str. charAt ( i) < '0' || str. charAt ( i) > '9' ) {
str = str. substring ( 0 , i) + " " + str. charAt ( i) + " " + str. substring ( i + 1 , str. length ( ) ) ;
i += 2 ;
}
}
Scanner sc = new Scanner ( str) ;
while ( sc. hasNext ( ) )
list. add ( sc. next ( ) ) ;
return list. toArray ( new String [ list. size ( ) ] ) ;
}
利用双栈实现不转化就求值(其实相当于上面的两个栈,只不过是把中缀表达式转化为后缀表达式的过程变为分别将op与数据分别存入不同的栈中,然后挨个操作,符号边进栈边计算)
重点是多了优先级的判断(*/±)。
package 栈;
import java. util. ArrayList;
import java. util. Scanner;
import java. util. Stack;
public class caculator {
public static void main ( String[ ] args) {
Scanner input = new Scanner ( System. in) ;
System. out. println ( "请输入一个算术表达式:" ) ;
String str = input. nextLine ( ) ;
compute ( str) ;
}
public static void compute ( String expression) {
String[ ] arr = strToExpressionArr ( expression) ;
if ( isLegalExpression ( arr) )
System. out. println ( compute ( strToExpressionArr ( expression) ) ) ;
else
System. out. println ( "请输入合法表达式" ) ;
}
private static String[ ] strToExpressionArr ( String str) {
ArrayList< String> list = new ArrayList < > ( ) ;
for ( int i = 0 ; i < str. length ( ) ; i++ ) {
if ( str. charAt ( i) < '0' || str. charAt ( i) > '9' ) {
str = str. substring ( 0 , i) + " " + str. charAt ( i) + " " + str. substring ( i + 1 , str. length ( ) ) ;
i += 2 ;
}
}
Scanner sc = new Scanner ( str) ;
while ( sc. hasNext ( ) )
list. add ( sc. next ( ) ) ;
return list. toArray ( new String [ list. size ( ) ] ) ;
}
private static int compute ( String[ ] expression) {
Stack< Integer> numStack = new Stack < > ( ) ;
Stack< Character> opStack = new Stack < > ( ) ;
for ( int i = 0 ; i < expression. length; i++ ) {
String ele = expression[ i] ;
if ( isNumber ( ele) ) {
numStack. push ( new Integer ( ele) ) ;
}
else if ( ele. charAt ( 0 ) == '+' || ele. charAt ( 0 ) == '-' ) {
while ( ! opStack. isEmpty ( ) && opStack. peek ( ) != '(' ) {
int b = numStack. pop ( ) ;
int a = numStack. pop ( ) ;
numStack. push ( getAnswer ( a, opStack. pop ( ) , b) ) ;
}
if ( ! opStack. isEmpty ( ) && opStack. peek ( ) == '(' )
opStack. pop ( ) ;
opStack. push ( ele. charAt ( 0 ) ) ;
}
else if ( ele. charAt ( 0 ) == '*' || ele. charAt ( 0 ) == '/' ) {
while ( ! opStack. isEmpty ( ) && opStack. peek ( ) != '(' &&
opStack. peek ( ) != '+' && opStack. peek ( ) != '-' ) {
int b = numStack. pop ( ) ;
int a = numStack. pop ( ) ;
numStack. push ( getAnswer ( a, opStack. pop ( ) , b) ) ;
}
if ( ! opStack. isEmpty ( ) && opStack. peek ( ) == '(' )
opStack. pop ( ) ;
opStack. push ( ele. charAt ( 0 ) ) ;
}
else if ( ele. charAt ( 0 ) == '(' ) {
opStack. push ( ele. charAt ( 0 ) ) ;
}
else if ( ele. charAt ( 0 ) == ')' ) {
while ( ! opStack. isEmpty ( ) && opStack. peek ( ) != '(' ) {
int b = numStack. pop ( ) ;
int a = numStack. pop ( ) ;
numStack. push ( getAnswer ( a, opStack. pop ( ) , b) ) ; }
if ( ! opStack. isEmpty ( ) && opStack. peek ( ) == '(' )
opStack. pop ( ) ;
}
}
if ( ! opStack. isEmpty ( ) ) {
int b = numStack. pop ( ) ;
int a = numStack. pop ( ) ;
numStack. push ( getAnswer ( a, opStack. pop ( ) , b) ) ;
}
return numStack. peek ( ) ;
}
private static boolean isNumber ( String s) {
for ( int i = 0 ; i < s. length ( ) ; i++ ) {
if ( s. charAt ( i) < '0' || s. charAt ( i) > '9' )
return false ;
}
return true ;
}
private static int getAnswer ( int a, char operator, int b) {
switch ( operator) {
case '+' : return a + b;
case '-' : return a - b;
case '*' : return a * b;
case '/' : return a / b;
}
return 0 ;
}
static boolean isLegalExpression ( String[ ] arr) {
char hc = arr[ 0 ] . charAt ( 0 ) ;
char tc = arr[ arr. length - 1 ] . charAt ( 0 ) ;
if ( hc == '+' || hc == '-' || hc == '*' || hc == '/' ||
tc == '+' || tc == '-' || tc == '*' || tc == '/' )
return false ;
Stack< Character> stk = new Stack ( ) ;
for ( String s : arr) {
if ( s. charAt ( 0 ) == '(' )
stk. push ( s. charAt ( 0 ) ) ;
else if ( s. charAt ( 0 ) == ')' ) {
if ( stk. isEmpty ( ) )
return false ;
stk. pop ( ) ;
}
}
if ( ! stk. isEmpty ( ) )
return false ;
String ts = "" ;
for ( String s : arr) {
ts += s;
}
for ( char c : ts. toCharArray ( ) ) {
if ( c != '+' && c != '-' && c != '*' && c != '/' && c != '(' && c != ')' && ! ( c >= '0' && c <= '9' ) )
return false ;
}
for ( int i = 0 ; i < arr. length; i++ ) {
char c = arr[ i] . charAt ( 0 ) ;
if ( isNumber ( arr[ i] ) ) {
boolean hasLeft = true ;
boolean hasRight = true ;
if ( i == 0 )
hasLeft = false ;
if ( i == arr. length - 1 )
hasRight = false ;
if ( i > 0 ) {
char cha = arr[ i - 1 ] . charAt ( 0 ) ;
if ( cha != '+' && cha != '-' && cha != '*' && cha != '/' )
hasLeft = false ;
}
if ( i < arr. length - 1 ) {
char cha = arr[ i + 1 ] . charAt ( 0 ) ;
if ( cha != '+' && cha != '-' && cha != '*' && cha != '/' )
hasRight = false ;
}
if ( ! hasLeft && ! hasRight)
return false ;
}
else if ( c == '+' || c == '-' || c == '*' || c == '/' ) {
boolean hasLeft = true ;
boolean hasRight = true ;
if ( i == 0 )
hasLeft = false ;
if ( i == arr. length - 1 )
hasRight = false ;
if ( i > 0 ) {
if ( ! isNumber ( arr[ i - 1 ] ) )
hasLeft = false ;
}
if ( i < arr. length - 1 ) {
if ( ! isNumber ( arr[ i + 1 ] ) )
hasRight = false ;
}
if ( ! hasLeft && ! hasRight)
return false ;
}
}
return true ;
}
}