数据结构与算法: 使用栈解决计算器问题
Posted android超级兵
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构与算法: 使用栈解决计算器问题相关的知识,希望对你有一定的参考价值。
数据结构与算法:使用栈解决计算器问题
Tips: 采用java语言, 关注博主,底部附有完整代码
使用到的知识点:
- 栈
- 中后缀表达式
- 后缀表达式
- 中缀表达式转后缀表达式
支持范围: + - * / 小括号() 小数点
例如:
案例一: 20 - 5 + 25 / 5 + 20 / 5 + 100 - 24 - 0.4
案例二: (3 + 5 + 2.5) - 2 * 5
效果图
案例一 | 案例二 |
---|---|
案例二思路分析图:
案例一(不带括号)
注释我写的很详细,直接看完整代码:
/**
* @author: android 超级兵
* @create: 2022-05-07 11:08
* TODO 使用栈来解决计算器计算问题
**/
public class Client
public static void main(String[] args)
// 结果 = 100
String str = "20-5+25/5+20/5+100-24-0.4";
// 用来存放数字
CalculatorStack numberStack = new CalculatorStack(str.length());
// 用来存放符号
CalculatorStack operatorStack = new CalculatorStack(str.length());
// 解析公式
List<String> parse = parseInfixFormula(str);
// 循环每一次 合理的入栈
for (String value : parse)
if (value == null)
continue;
// 判断是否是数字
if (isNumber(value))
// 数字
numberStack.push(Float.parseFloat(value));
else
// 符号
char operator = value.charAt(0);
// System.out.println("符号:" + operator);
// 判断符号栈是否为null
if (operatorStack.isEmpty())
// 符号第一次加载的时候 直接添加进去
operatorStack.push(operator);
else
// 不是第一次加载
// 先判断优先级
if (getLevel(operator) < getLevel((char) operatorStack.seeHeadData()))
// 如果当前优先级 < 顶部的优先级
// 例如 即将添加的符号为 + , 顶部的符号为 *
// 那么先取出数栈中2个数,和符号栈中一个数 计算
// 最终将计算结果在添加到数栈中...
float num1 = numberStack.pop();
float num2 = numberStack.pop();
char oper = (char) operatorStack.pop();
float result = result(num1, num2, oper);
System.out.printf("先计算:%.1f %c %.1f = %.1f\\n", num2, oper, num1, result);
numberStack.push(result);
operatorStack.push(operator);
else
// 如果优先级相等 则直接加入
operatorStack.push(operator);
// 反转数据!
numberStack.reverse();
operatorStack.reverse();
// 计算最终结果
while (!operatorStack.isEmpty())
float num1 = numberStack.pop();
float num2 = numberStack.pop();
char operator = (char) operatorStack.pop();
float result = result(num2, num1, operator);
System.out.printf("计算:%.1f %c %.1f = %.1f\\n", num1, operator, num2, result);
numberStack.push(result);
System.out.println("最终结果为:" + str + " = " + numberStack.seeHeadData());
使用数组模拟栈
/**
* @author: android 超级兵
* @create: 2022-05-07 11:10
**/
public class CalculatorStack
// 用来存放数据
float[] mStacks;
// top的坐标
int currentIndex = -1;
/**
* @param max 栈的最大值
*/
public CalculatorStack(int max)
mStacks = new float[max];
public synchronized void push(float value)
// 判断栈是否满
if (isFull())
System.out.println("栈满了~~");
return;
currentIndex++;
mStacks[currentIndex] = value;
// 懒的判断是否为null了
public float seeHeadData()
try
return mStacks[currentIndex];
catch (Exception e)
return 0;
// 弹出
public synchronized float pop()
if (isEmpty())
throw new NullPointerException("栈空了");
float value = mStacks[currentIndex];
mStacks[currentIndex] = 0;
currentIndex--;
return value;
public synchronized void show()
for (int i = mStacks.length - 1; i >= 0; i--)
if (mStacks[i] != 0)
System.out.println(mStacks[i]);
System.out.println();
public void showChar()
for (int i = mStacks.length - 1; i >= 0; i--)
if (mStacks[i] != 0)
System.out.println((char) mStacks[i]);
System.out.println();
/*
* @author: android 超级兵
* @create: 2022/5/7 18:09
* TODO 反转数据
*/
public synchronized void reverse()
float[] tempInts = new float[mStacks.length];
int index = 0;
while (!isEmpty())
tempInts[index++] = pop();
for (float value : tempInts)
if (value != 0)
push(value);
/*
* @author: android 超级兵
* @create: 2022/5/7 11:15
* TODO 是否栈满
*/
public boolean isFull()
return currentIndex == mStacks.length;
/*
* @author: android 超级兵
* @create: 2022/5/7 11:15
* TODO 是否栈空
*/
public boolean isEmpty()
return currentIndex == -1;
运行结果:
先计算:25.0 / 5.0 = 5.0
先计算:20.0 / 5.0 = 4.0
计算:20.0 - 5.0 = 15.0
计算:15.0 + 5.0 = 20.0
计算:20.0 + 4.0 = 24.0
计算:24.0 + 100.0 = 124.0
计算:124.0 - 24.0 = 100.0
计算:100.0 - 0.4 = 99.6
最终结果为:20-5+25/5+20/5+100-24-0.4 = 99.6
案例二(带括号)
/**
* @author: android 超级兵
* @create: 2022-05-09 00:43
* TODO 解决计算器中带有括号的优先级
* 例如: 中缀表达式: ( 3 + 4 ) * 5 - 6 = 29
* 后缀表达式: 3 4 + 5 * 6 -
**/
public class Client
public static void main(String[] args)
// 后缀
// String formula = "3 4 + 5 * 6 -";
// // 解析后缀表达式
// List<String> str = FormulaUtil.parseSuffixFormula(formula);
// 中缀
String formula = "(3 + 5 + 2.5) - 2 * 5";
// 中缀 转 后缀
List<String> str = FormulaUtil.inFixToSuffix(formula);
Stack<String> numberStack = new Stack<>();
for (String item : str)
if (FormulaUtil.isNumber(item))
// 数字
// System.out.println("数字:" + item);
// 数字直接入栈
numberStack.push(item);
else
// 符号
// System.out.println("符号:" + item);
float number1 = Float.parseFloat(numberStack.pop());
float number2 = Float.parseFloat(numberStack.pop());
char oper = item.charAt(0);
float res = FormulaUtil.result(number1, number2, oper);
System.out.printf("计算:%.1f %c %.1f = %.1f\\n", number2, oper, number1, res);
numberStack.push(String.valueOf(res));
System.out.println("最终结果为:" + numberStack.pop());
FormulaUtil 辅助类
/**
* @author: android 超级兵
* @create: 2022-05-09 00:48
* TODO 公式辅助类
**/
public class FormulaUtil
/*
* @author: android 超级兵
* @create: 2022/5/9 01:21
* TODO 中缀转后缀
* 例如 (3 + 5) * 2 - 5 => 3 5 + 2 * 5 -
* (4 + (8 - 5) * 3 - 5 => 4 8 5 - + 3 * 5 -
*/
public static List<String> inFixToSuffix(String infix)
List<String> infixList = parseInfixFormula(infix);
// 存放符号元素
Stack<String> elementStack = new Stack<>();
// 存放符号 + 数字元素
ArrayList<String> elementList = new ArrayList<>();
for (String item : infixList)
if (isNumber(item))
// 数字
elementList.add(item);
else if (item.equals("("))
elementStack.push(item);
else if (item.equals(")"))
while (!elementStack.peek().equals("("))
String pop = elementStack.pop();
elementList.add(pop);
// 弹出 )
elementStack.pop();
else
// 符号
// System.out.println("符号为:" + item);
if (elementStack.size() != 0 && getLevel(elementStack.peek().charAt(0)) > getLevel(item.charAt(0)))
// 如果 栈顶等级 > 当前符号的等级
elementList.add(elementStack.pop());
// 将当前符号压入栈中
elementStack.push(item);
// 将 elementStack 中剩余元素 添加到 elementList中
while (elementStack.size() != 0)
elementList.add(elementStack.pop());
System.out.println("中缀为:" + infix);
System.out.println("中缀转后缀最终结果为:");
for (String o : elementList)
System.out.println(o);
return elementList;
/*
* @author: android 超级兵
* @create: 2022/5/9 01:05
* TODO 解析后缀表达式 例如str = "3 4 + 5 * 6 -";
* 解析后:
* 3
* 4
* +
* 5
* *
* 6
* -
* tips: 注意后缀表达式格式,每个元素之间空格隔开!
*/
public static List<String> parseSuffixFormula(String str)
return Arrays.asList(str.split(" "));
/*
* @author: android 超级兵
* @create: 2022/5/7 15:41
* TODO 解析中缀表达式 例如 str = "62-5+25/5";
* 解析后:
* 62
* -
* 5
* +
* 25
* /
* 5
*/
public static ArrayList<String> parseInfixFormula(String str)
StringBuilder temp = new StringBuilder();
ArrayList<String> numbers = new ArrayList<>();
// 消除所有的空格
str = str.replaceAll(" ", "");
for (int i = 0; i < str.length(); i++)
char indexValue = str.charAt(i);
// 判断是否是符号
if (isOperator(indexValue))
// System.out.println("符号:" + indexValue);
// 是符号
numbers.add(String.valueOf(indexValue));
else
// 是数字
// System.out.println("数字:" + indexValue);
int check = (int) indexValue - 48;
// 46代表小数点
// ASCII码对照表: https://www.habaijian.com/
if ((check < 0 || check > 9) && indexValue != 46)
throw new RuntimeException("存在特殊符号");
// 是否是最后一位数字
if (i == str.length() - 1)
// 直接添加
numbers.add(String.valueOf(temp) + indexValue);
else
// 如果不是符号,则一直记录
temp.append(indexValue);
// 判断下一位是否是符号
if (isOperator(str.charAt(i + 1)))
// 符号
numbers.add(temp.toString());
// 清空stringBuilder
temp = new StringBuilder();
System.out.println("解析完成:");
for (String number : numbers)
if (null != number)
System.out.println(number);
System.out.println();
return numbers;
/**
* TODO 是否是符号(+ , - , * , /)
*/
public static boolean isOperator(char value)
return value == '+'
以上是关于数据结构与算法: 使用栈解决计算器问题的主要内容,如果未能解决你的问题,请参考以下文章