文章目录
1.栈实现计算器(中缀表达式)1.1流程图1.2 代码实现
2. 逆波兰(后缀)表达式实现2.1 初步实现2.2 中缀表达式转后缀表达式2.2.1步骤2.2.2 代码实现
1.栈实现计算器(中缀表达式)
1.1流程图
1.2 代码实现
public class Calculator {
public static void main(String
[] args
) {
String expression
= "700*2*2-5+1-5+3-4";
ArrayStackCal numStack
= new ArrayStackCal(10);
ArrayStackCal operStack
= new ArrayStackCal(10);
int index
= 0;
int num1
= 0;
int num2
= 0;
int oper
= 0;
int res
= 0;
char ch
= ' ';
String keepNum
= "";
while (true){
ch
= expression
.substring(index
,index
+1).charAt(0);
if (operStack
.isOper(ch
)) {
if (!operStack
.isEmpty()){
if (operStack
.priority(ch
) <= operStack
.priority(operStack
.peek())) {
num1
= numStack
.pop();
num2
= numStack
.pop();
oper
= operStack
.pop();
res
= operStack
.cal(num1
, num2
, oper
);
numStack
.push(res
);
operStack
.push(ch
);
} else {
operStack
.push(ch
);
}
}else {
operStack
.push(ch
);
}
}else {
keepNum
+= ch
;
if (index
== expression
.length() - 1) {
numStack
.push(Integer
.parseInt(keepNum
));
}else{
if (operStack
.isOper(expression
.substring(index
+1,index
+2).charAt(0))) {
numStack
.push(Integer
.parseInt(keepNum
));
keepNum
= "";
}
}
}
index
++;
if (index
>=expression
.length()){
break;
}
}
while (true){
if (operStack
.isEmpty()){
break;
}
num1
= numStack
.pop();
num2
= numStack
.pop();
oper
= operStack
.pop();
res
= operStack
.cal(num1
,num2
,oper
);
numStack
.push(res
);
}
int res2
= numStack
.pop();
System
.out
.println("表达式"+expression
+"="+res2
);
}
}
class ArrayStackCal extends ArrayStack{
public ArrayStackCal() {
}
public ArrayStackCal(int maxSize
) {
super(maxSize
);
}
public int priority(int oper
){
if (oper
=='*'||oper
=='/'){
return 1;
}else if (oper
=='+' || oper
=='-'){
return 0;
}else {
return -1;
}
}
public boolean isOper(char val
){
return val
=='+' ||val
=='-' || val
=='*'|| val
=='/';
}
public int cal(int num1
,int num2
,int oper
){
int res
= 0;
switch (oper
){
case '+':
res
= num2
+ num1
;
break;
case '-':
res
= num2
- num1
;
break;
case '*':
res
= num2
* num1
;
break;
case '/':
res
= num2
/ num1
;
break;
default:
break;
}
return res
;
}
}
ArrayStack
class ArrayStack implements Stack1{
public int maxSize
;
public int[] stack
;
public int top
= -1;
public ArrayStack() {
}
public ArrayStack(int maxSize
) {
this.maxSize
= maxSize
;
stack
=new int[this.maxSize
];
}
@Override
public int getSize() {
return stack
.length
;
}
@Override
public boolean isEmpty() {
return top
==-1;
}
@Override
public void push(int value
) {
if (isFull()){
System
.out
.println("栈满!");
return;
}
top
++;
stack
[top
]=value
;
}
public boolean isFull(){
return top
==maxSize
-1;
}
@Override
public int pop() {
if (isEmpty()){
throw new RuntimeException("栈空,无法取出数据!");
}
int value
= stack
[top
];
top
--;
return value
;
}
@Override
public int peek() {
return stack
[top
];
}
public void traverse(){
if (isEmpty()){
System
.out
.println("栈空,无法取出数据!");
return;
}
for (int i
= top
; i
>=0 ; i
--) {
System
.out
.println("stack["+i
+"]"+"="+stack
[i
]);
}
}
}
stack1
public interface Stack1 {
int getSize();
boolean isEmpty();
void push(int e
);
int pop();
int peek();
}
2. 逆波兰(后缀)表达式实现
例如:(3+4)X5-6对应的后缀表达式就是,针对后缀表达式求值步骤如下: 1.从左至右扫描,将3和4压入堆栈; 2.遇到+运算符,因此弹出4和3 (4为栈顶元素,3为次顶元素),计算出3+4的值,得7,再将7入栈; 3.将5入栈; 4.接下来是X运算符,因此弹出5和7,计算出7X5=35,将35入栈; 5.将6入栈; 6.最后是-运算符,计算出35-6的值,即29,由此得出最终结果
2.1 初步实现
实现思路
定义表达式
将表达式按空格分割放入列表
计算结果 :从左到右扫描,扫到的是数字就入栈,符号就pop出两个数字然后进行运算,再将结果入栈循环执行。直到最后还在栈中的元素就是结果。
返回结果
public class PolanNotation {
public static void main(String
[] args
) {
String expression
= "3 4 + 5 * 6 -";
ArrayList
<String> list
= getListString(expression
);
System
.out
.println(list
);
int cal
= cal(list
);
System
.out
.println(cal
);
}
public static ArrayList
<String> getListString(String expression
){
String
[] s
= expression
.split(" ");
ArrayList
<String> list
= new ArrayList<>();
for (String s1
: s
) {
list
.add(s1
);
}
return list
;
}
public static int cal(ArrayList
<String> list
){
Stack
<String> stack
= new Stack<>();
int num1
= 0;
int num2
= 0;
int res
= 0;
for (String s
: list
) {
if(s
.matches("\\d+")){
stack
.push(s
);
}else {
num1
= Integer
.parseInt(stack
.pop());
num2
= Integer
.parseInt(stack
.pop());
switch (s
){
case "+":
res
= num2
+num1
;
break;
case "-":
res
= num2
-num1
;
break;
case "*":
res
= num2
*num1
;
break;
case "/":
res
= num2
/num1
;
break;
default:
throw new RuntimeException("运算符有误");
}
stack
.push(""+res
);
}
}
return Integer
.parseInt(stack
.pop());
}
}
这里表达式是后缀表达式,下面添加中缀转后缀表达式的实现。
2.2 中缀表达式转后缀表达式
2.2.1步骤
1)初始化两个栈:运算符栈s1和储存中间结果的栈s2; 2)从左至右扫描中缀表达式; . 3)遇到操作数时,将其压s2; 4)遇到运算符时,比较其与s1栈顶运算符的优先级: 1.如果s1为空,或栈顶运算符为左括号“(”,则直接将此运算符入栈; 2.否则,若优先级比栈顶运算符的高,也将运算符压入s1; 3.否则,将s1栈顶的运算符弹出并压入到s2中,再次转到(4-1)与s1中新的栈顶运算符相比较; 5)遇到括号时: (1) 如果是左括号“(”,则直接压入s1 (2)如果是右括号“)”,则依次弹出s1栈顶的运算符,并压入s2,直到遇到左括号为止,此时将这一对括号丢弃 6)重复步骤2至5,直到表达式的最右边 7)将s1中剩余的运算符依次弹出并压入s2 8)依次弹出s2中的元素并输出,结果的逆序即为中缀表达式对应的后缀表达式
举例 1+((2+3)X4)-5
扫描到的元素s2 (栈底->栈顶)s1(栈底->栈顶)说明
11空数字,入栈s2+1+s1为空,入栈s1(1+ (左括号,入栈s1(1+ ( (左括号,入栈s121 2+ ( (数字,入栈s2+1 2+ ( ( +s1栈顶为左括号 ,入栈s131 2 3+ ( ( +数字,入栈s2)1 2 3 ++ (右括号,弹出运算符直到遇到左括号*1 2 3 ++ ( *s1栈顶为左括号,入栈s141 2 3 + 4+ ( *数字,入栈s2)1 2 3 + 4 *+右括号,弹出运算符直到遇到左括号-1 2 3 + 4 * +--与+优先级相同,弹出+,压入-51 2 3 + 4 * + 5-数字,入栈s2扫描结束1 2 3 + 4 * + 5 -空s1剩余运算符压入s2
2.2.2 代码实现
public class PolanNotation {
public static void main(String
[] args
) {
String expression2
= "1+((2+3)*4)-5";
List
<String> list1
= toInfixExpressionList(expression2
);
System
.out
.println("转换前"+list1
);
List
<String> list2
= parseSuffixExpreesionList(list1
);
System
.out
.println("转换后"+list2
);
int res
= cal(list2
);
System
.out
.println(expression2
+"="+res
);
}
public static List
<String> parseSuffixExpreesionList(List
<String> list
){
Stack
<String> s1
= new Stack<>();
List
<String> s2
= new ArrayList<>();
for (String s
: list
) {
if (s
.matches("\\d+")){
s2
.add(s
);
}else if(s
.equals("(")) {
s1
.push(s
);
}else if(s
.equals(")")){
while (!s1
.peek().equals("(")) {
s2
.add(s1
.pop());
}
s1
.pop();
}else {
while (s1
.size()!=0 && Operation
.getValue(s1
.peek())>= Operation
.getValue(s
)){
s2
.add(s1
.pop());
}
s1
.push(s
);
}
}
while (s1
.size() !=0){
s2
.add(s1
.pop());
}
return s2
;
}
public static List
<String> toInfixExpressionList(String s
){
List
<String> list
= new ArrayList<>();
String str
;
char c
;
int i
=0;
do {
if ((c
=s
.charAt(i
))<48||(c
=s
.charAt(i
))>57){
list
.add(""+c
);
i
++;
}else {
str
="";
while (i
<s
.length() && (c
=s
.charAt(i
))>=48 &&(c
=s
.charAt(i
))<=57){
str
+=c
;
i
++;
}
list
.add(str
);
}
}while (i
< s
.length());
return list
;
}
public static List
<String> getListString(String expression
){
String
[] s
= expression
.split(" ");
List
<String> list
= new ArrayList<>();
for (String s1
: s
) {
list
.add(s1
);
}
return list
;
}
public static int cal(List
<String> list
){
Stack
<String> stack
= new Stack<>();
int num1
= 0;
int num2
= 0;
int res
= 0;
for (String s
: list
) {
if(s
.matches("\\d+")){
stack
.push(s
);
}else {
num1
= Integer
.parseInt(stack
.pop());
num2
= Integer
.parseInt(stack
.pop());
switch (s
){
case "+":
res
= num2
+num1
;
break;
case "-":
res
= num2
-num1
;
break;
case "*":
res
= num2
*num1
;
break;
case "/":
res
= num2
/num1
;
break;
default:
throw new RuntimeException("运算符有误");
}
stack
.push(""+res
);
}
}
return Integer
.parseInt(stack
.pop());
}
}
class Operation {
private static int ADD
= 1;
private static int SUB
= 1;
private static int MUL
= 2;
private static int DIV
= 2;
public static int getValue(String operation
) {
int result
= 0;
switch (operation
) {
case "+":
result
= ADD
;
break;
case "-":
result
= SUB
;
break;
case "*":
result
= MUL
;
break;
case "/":
result
= DIV
;
break;
default:
break;
}
return result
;
}
}