最近开始学习数据结构,已了解:顺式线性表-链式线性表-栈-队列。做个小应用,巩固下知识。
该计算器 能运算所有四则运算,不包括括号。
概念解释:
我们平时说的四则运算表达式又叫逆波兰表达式,或者中缀表达式,及运算符中两个数之间
后缀表达式:运算符在两个数之后,且从左向右运算,没有运算符优先级
例如:1 2 + ,1为被加数,2为加数变成四则运算为 1+2 =3。
再例如:1 2 + 4 * :先运算第一个符号“+”变成 3 4 * ,在运算“*”,结果是12。
ok,计算器编写的核心就在于将中缀表达式变成 能遍历的后缀表达式。
而难点又在与优先级的转换,我这里定义的转换规则是:
数字输出,运算符进栈,栈顶符号优先级高输出,低/等于压栈
代码如下:
package com.study.stack;
import java.util.Stack;
/**
* @author lvbowei
* @date 2019/8/29
*/
public class Jisuanqi {
static Stack<Object> shu = new Stack<>();
static Stack<Character> fu = new Stack<>();
public static void main(String[] args) {
String s = "1+2*3-10/2";
Stack stack = toHouZhui(s);
System.out.println("后缀表达式:"+stack.toString());
//倒叙
Stack endStack = new Stack();
int size = stack.size();
for (int i = 0; i < size; i++) {
endStack.push(stack.pop());
}
//这里用链表进行计算,只为了熟悉链表,你们可以使用栈也是很不错的。
Node<Object> prevNode = null;
int size1 = endStack.size();
for (int i = 0; i < size1; i++) {
Object c = endStack.pop();
if (c.equals('+')||c.equals('-')||c.equals('*')||c.equals('/')){
//
String sss = prevNode.prev.item.toString()+c+prevNode.item.toString();
System.out.println("计算过程:"+sss);
Double left = Double.valueOf(prevNode.prev.item.toString());
Double right = Double.valueOf(prevNode.item.toString());
Double result ;
if (c.equals('+')){
result = left + right;
}else if (c.equals('-')){
result = left - right;
}else if (c.equals('*')){
result = left * right;
}else{
result = left / right;
}
Node<Object> objectNode = new Node<>(prevNode.prev.prev, result);
prevNode.prev = null;//赋null ,gc
prevNode = objectNode;
}else{
Node<Object> objectNode = new Node<>(prevNode, c);
prevNode = objectNode;
}
}
System.out.println("计算结果:"+prevNode.item);
}
private static class Node<E>{
E item;
Node<E> prev;
Node(Node<E> prev,E item){
this.prev = prev;
this.item = item;
}
}
private static Stack toHouZhui(String s) {
char[] chars = s.toCharArray();
String temp = "";
for (int i = 0; i < chars.length; i++) {
char c = chars[i];
if (c=='+'||c=='-'||c=='*'||c=='/'){
if (!temp.equals("")){
temp = pushShu(shu, temp);
}
pushFu(fu, c);
}else{
temp+=c;
if (i==(chars.length-1)){
temp = pushShu(shu, temp);
}
}
}
int size = fu.size();
for (int i = 0; i < size; i++) {
Character top = fu.pop();
shu.push(top);
}
return shu;
}
private static void pushFu(Stack<Character> fu, char c) {
int size = fu.size();
for (int i = 0; i < size; i++) {
Character top = fu.peek();
if (compare(top,c)){//栈顶优先级高输出
shu.push(fu.pop());
}else {
break;
}
}
fu.push(c);
}
private static String pushShu(Stack<Object> shu, String temp) {
shu.push(Double.valueOf(temp));
return "";
}
/**
* 比较运算符的优先级
* @param a
* @param b
* @return true:a 比 b 高 ,输出;false a <= b,压栈
* a 必须为栈顶
*/
private static boolean compare(char a,char b){
if ((a=='+'||a=='-')){
return false;
}
return true;
}
}
运算结果:
后缀表达式:[1.0, 2.0, 3.0, *, 10.0, 2.0, /, -, +]
计算过程:2.0*3.0
计算过程:10.0/2.0
计算过程:6.0-5.0
计算过程:1.0+1.0
计算结果:2.0