大家好,我是皮皮猫吖!
每文一言:人生最低谷的时候那只是在缓冲,是达到最高点必须经过的地方。
本篇文章:
主要是关于java数据结构与算法的一些应用:栈实现四则表达式计算、栈实现带符号的四则表达式计算。
正文如下:
一、应用一:栈结构实现四则表达式计算
1)简单四则表达式计算的实现流程:
2)简单四则表达式的代码分析:
package com.data.structure.study4.stack;
/**
* @author imppm
* @create 2021-03-09-20:26
*/
public class Stack3CalculatorStack1 {
public static void main(String[] args) {
Stack3 stack3 = new Stack3();
stack3.compute("7*2*2-5+1-5+3-4");//18
stack3.compute("100-2-3*2");//104
}
}
class Stack3{
//栈数组:存储运算符
private char[] operatorStack = new char[10];
//栈数组:存储数据
private int[] dataStack = new int[10];
//设置加法的优先级
private final int sumPriority = 0;
//设置减法的优先级
private final int subPriority = 0;
//设置乘法的优先级
private final int mulPriority = 1;
//设置除法的优先级
private final int divPriority = 1;
//数据索引
private int dataTop = -1;
//运算符索引
private int operatorTop = -1;
//运算和
private int dataSum = 0;
//表达式的计算
public void compute(String data){
int continuous = 0;
//循环字符串
for (int i = 0; i < data.length(); i++){
//当前字符串字符为数字
if(data.charAt(i)>='0' && data.charAt(i)<='9'){
//判断是否是多位数
continuous++;
//如果连续值大于1,表示连续多个字符是数字,对栈存储的数字进行更新
if(continuous>1){
dataStack[dataTop] = dataStack[dataTop] * 10 + (data.charAt(i)-'0');
}else {
//直接将数据字符压入到数据栈中
dataStack[++dataTop] = data.charAt(i) - '0';
}
//输入最后一个数据:进行计算
if(i+1 == data.length()){
//指导运算符栈为空
while(!operatorStackIsEmpty()){
//拿出数据栈顶元素
int data1 = dataStack[dataTop--];
//数据栈顶元素的下一个元素
int data2 = dataStack[dataTop--];
//使用运算符进行计算
dataSum = operatorCompute(data2, data1, operatorStack[operatorTop--]);
//将计算之后的值,放入到数据栈中
dataStack[++dataTop] = dataSum;
}
}
}
//当前字符为运算符
else {
//出现运算符,数字连续值就置为0
continuous = 0;
//如果运算符栈为空:直接压入栈中
if(operatorStackIsEmpty()){
operatorStack[++operatorTop] = data.charAt(i);
}
//运算符栈不为空
else{
//当前运算符的优先级大于栈顶运算符的优先级:运算符直接压入运算符栈中
if(!isStackOperatorPriorityBig(data.charAt(i))){
operatorStack[++operatorTop] = data.charAt(i);
}
//当前运算符的优先级小于等于栈顶运算符优先级:拿出栈顶运算符进行计算
else{
while (isStackOperatorPriorityBig(data.charAt(i))){
//获取栈顶运算符
char stackTopOperator = getStackTopOperator();
//获取栈顶数据1
int data1 = dataStack[dataTop--];
//获取栈顶数据2
int data2 = dataStack[dataTop--];
//数据1、数据2进行栈顶运算符操作
dataSum = operatorCompute(data2, data1, stackTopOperator);
//数据栈更新数据
dataStack[++dataTop] = dataSum;
//运算符栈顶元素-1
operatorTop--;
//判断运算符栈是否为空
if(operatorStackIsEmpty()){
break;
}
}
//把当前这个运算符压入到数据栈中
operatorStack[++operatorTop] = data.charAt(i);
}
}
}
}
System.out.println("计算结果为:"+dataSum);
}
//判断运算符栈是否为空
private boolean operatorStackIsEmpty(){
return operatorTop == -1;
}
//获取运算符栈栈顶元素
private char getStackTopOperator(){
return operatorStack[operatorTop];
}
//获取运算符的优先级
private int getPriority(char operator){
switch (operator){
case '+':
return sumPriority;
case '-':
return subPriority;
case '*':
return mulPriority;
case '/':
return divPriority;
default:
return -1;
}
}
//使用对应的运算符进行计算
private int operatorCompute(int a, int b, char operator){
switch (operator){
case '+':
return a + b;
case '-':
return a - b;
case '*':
return a * b;
case '/':
return a / b;
default:
return -1;
}
}
//判断运算符栈顶元素与当前运算符的优先级
private boolean isStackOperatorPriorityBig(char operator){
//获取栈顶的运算符数据
char topOperatorData = getStackTopOperator();
//获取到栈顶运算符的优先级
int topDataPriority = getPriority(topOperatorData);
//获取要加入栈中运算符的优先级
int currentPriority = getPriority(operator);
//如果栈顶的运算符的优先级大于当前运算符的优先级,计算栈顶数据
if(topDataPriority >= currentPriority){
return true;
}else{
//将运算符加入到运算符栈中
return false;
}
}
}
二、应用二:栈结构实现带小括号的四则表达式计算:(1 + 2) - 3 * 4 + 2 * (1+2) = -3
1)带小括号的四则表达式的实现过程
2)带小括号的四则表达式的代码分析:
package com.data.structure.study4.stack;
/**
* 含小括号的四则运算:
* 如何处理小括号:
* 设置左括号的优先级为最大值,设置右括号的优先级为最小级
* ① 如果左括号的优先级大于栈顶优先级,左括号入栈
* ② 如果栈顶元素为"(",当前运算符不为")",直接将这个运算符压入栈中
* ③ 如果栈顶元素为"(",当前运算符为")",直接将这"("运算符出栈,右括号运算符也不入栈
* @author imppm
* @create 2021-03-11-8:14
*/
public class Stack3CalculatorStack2 {
public static void main(String[] args) {
Stack4 stack4 = new Stack4();
//stack4.compute("7*2*2-5+1-5*3-4");//18
//stack4.compute("7*2*2-2*1-5*3-4");//7
//stack4.compute("100-(2-3)*2");//104
stack4.compute("(1+2)-3*4+2*(1+2)");//3-12+6=-3
}
}
class Stack4 {
//创建数据栈
private int[] dataStack = new int[10];
//创建运算符栈
private char[] operatorStack = new char[10];
//加法运算符的优先级
private final int sumPriority = 0;
//减法运算符的优先级
private final int subPriority = 0;
//乘法运算符的优先级
private final int mulPriority = 1;
//除法运算符的优先级
private final int divPriority = 1;
//左括号运算符的优先级
private final int leftBracketsPriority = 2;
//右括号运算符的优先级
private final int rightBracketPriority = -1;
//数据栈栈顶指针
private int dataTop = -1;
//运算符栈栈顶指针
private int operatorTop = -1;
//运算符标记位:出栈,入栈的标志
private int operatorFlag = 0;
//数据标志位:出栈、入栈的标志位
private int dataFlag = 1;
//获取运算符的优先级
private int getOperatorPriority(char ch) {
switch (ch) {
case '+':
return sumPriority;
case '-':
return subPriority;
case '*':
return mulPriority;
case '/':
return divPriority;
case '(':
return leftBracketsPriority;
case ')':
return rightBracketPriority;
default:
throw new RuntimeException("无法获取该字符的优先级!");
}
}
//算式运算
public void compute(String data) {
//用来判断是否连续输入数字
boolean flag = false;
// 遍历字符串
for (int i = 0; i < data.length(); i++) {
char ch = data.charAt(i);
//是数字:直接压入数据栈中
if (isDigit(ch)) {
if(flag){
//获取到当前栈的第一个数据
int i1 = (int)pop(dataFlag);
//连续输入字符:拿到当前栈顶数据,数据*10+读取到的下一位
push(i1*10 + (ch - '0'));
}else{
//没有连续输入数字,直接压入数据栈中
push((int) (ch - '0'));
}
flag = true;
}
//是字符
else {
flag = false;
//栈中无运算符,将该运算符压入运算符栈中
if (operatorTop == -1) {
push(ch);
continue;
}
//输出运算符栈
while(true) {
if(operatorTop==-1){
break;
}
//栈中有运算符
//获取栈顶运算符
char operatorStackTopDat = getOperatorStackTopData();
//如果栈顶元素优先级小于当前运算符优先级,将当前运算符直接压入栈中
if (getOperatorPriority(ch) > getOperatorPriority(operatorStackTopDat)) {
//直接将运算符压入栈中
push(ch);
break;
}
//栈顶元素优先级大于等于当前运算符优先级,进行计算
else {
//获取到运算符栈栈顶元素
char operator = (char) pop(operatorFlag);
//如果栈顶运算符为'('的时候,
//无法进行运算符操作,直接将"("和该运算符都压入栈中
if(operator=='(' && ch!=')'){
push('(');
push(ch);
break;
}
//如果运算符栈顶元素为'(',当前ch为')',直接跳出
else if(operator=='('){
break;
}
//上一个运算符不为'(',进行计算
//数据栈栈顶数据1
int num1 = (int) pop(dataFlag);
//数据栈栈顶数据2
int num2 = (int) pop(dataFlag);
//使用运算符计算的结果
int num = operatorCompute(num1, num2, operator);
//将计算的结果压入栈中
push(num);
//当前运算符栈为空,将当前运算符压入栈中
if(operatorTop==-1){
push(ch);
break;
}
}
}
}
}
//最后一步:遍历运算符栈
//如果操作符栈为空
while (operatorTop!=-1){
//获取操作符栈数据
char operator = (char)pop(operatorFlag);
//获取数据栈栈顶数据1
int num1 = (int)pop(dataFlag);
//获取数据栈栈顶数据2
int num2 = (int)pop(dataFlag);
//通过运算符进行运算
int num = operatorCompute(num1, num2, operator);
//将运算结果压入到数据栈中
push(num);
}
System.out.println(data+" = "+dataStack[dataTop]);
}
public boolean isDigit(char ch) {
return ch >= '0' && ch <= '9';
}
//两个数据进行操作符运算
private int operatorCompute(int a, int b, char ch) {
switch (ch) {
case '+':
return a + b;
case '-':
return b - a;
case '*':
return a * b;
case '/':
return b / a;
default:
throw new RuntimeException("无法获取该字符的优先级!");
}
}
//获取操作符栈顶元素
public char getOperatorStackTopData() {
return operatorStack[operatorTop];
}
//入栈
public void push(Object data) {
if (data instanceof Integer) {
int i = (Integer) data;
dataStack[++dataTop] = i;
} else {
char ch = (Character) data;
operatorStack[++operatorTop] = ch;
}
}
//出栈
public Object pop(int choice) {
//如果传入的是1,数据栈栈顶元素出栈
if (choice == 1) {
if (dataTop == -1) {
throw new RuntimeException("数据栈空!无数据出栈!");
}
return dataStack[dataTop--];
}
//如果传入的是0,运算符栈栈顶元素出栈
else {
if (operatorTop == -1) {
throw new RuntimeException("运算符栈空!无数据出栈!");
}
return operatorStack[operatorTop--];
}
}
}
希望本篇文章对大家有所帮助,后续会继续分享java数据结构与算法相关学习知识…
如果文章内容有错误的地方,请在留言处留下你的见解,方便大家共同学习。谢谢!
如有侵权或其他任何问题请联系:QQ1370922071,本文主要用于学习交流,转载请声明!
作者:皮皮猫吖