蓝桥杯: 算法训练 表达式计算
问题描述
输入一个只包含加减乖除和括号的合法表达式,求表达式的值。其中除表示整除。
输入格式
输入一行,包含一个表达式。
输出格式
输出这个表达式的值。
样例输入
1-2+3*(4-5)
样例输出
-4
数据规模和约定
表达式长度不超过100,表达式运算合法且运算过程都在int内进行。
import java.util.Scanner;
class characterNum {
int length;
int[] num;// 用来存数字
char[] fuhao;// 用来存符号
boolean[] isEmpty;// 判断是否为空
// 三串各类型数组
//例:9+44*(8-2/1)
// num:[9, ,44, , , ,8, ,2, ,1, ]
//fuhao:[ ,+, , ,*,(, ,-, ,/, ,)]
//isEmpty:[false,false,false,true,false,false,false,false,false,false,false]
/**
*构造初始化
*/
public characterNum(int N) {
length = N;
num = new int[N];
fuhao = new char[N];
isEmpty = new boolean[N];
}
// 格式化整个String,数字存num里,符号存符号里,中间数字里留的的空设isEmpty=true
void structured(String getin) {
for (int i = 0; i < length; i++) {
if (getin.charAt(i) == '+') {
fuhao[i] = '+';
isEmpty[i] = false;
} else if (getin.charAt(i) == '-') {
fuhao[i] = '-';
isEmpty[i] = false;
} else if (getin.charAt(i) == '*') {
fuhao[i] = '*';
isEmpty[i] = false;
} else if (getin.charAt(i) == '/') {
fuhao[i] = '/';
isEmpty[i] = false;
} else if (getin.charAt(i) == '(') {
fuhao[i] = '(';
isEmpty[i] = false;
} else if (getin.charAt(i) == ')') {
fuhao[i] = ')';
isEmpty[i] = false;
} else if (getin.charAt(i) == '#') {
isEmpty[i] = true;
} else {
for (int j = i; j < length; j++) {
if (getin.charAt(j) < '0' || getin.charAt(j) > '9') {
// 循环处理连续的char型数字转为一个int数字
for (int temp = i, cout = 1; temp != j; temp++, cout++) {
num[i] += ((int) getin.charAt(temp) - 48) * (int) (Math.pow(10, j - i - cout));
}
i = j - 1;// 返回是符号的前一个值给i,方便下次循环i++个存为符号
break;
} else {
if (i == j) {
isEmpty[i] = false;// 标记第一个i的时候不为空
}
if (j != i) {
isEmpty[j] = true;// 后续的都标记为空
}
}
}
}
}
/*
* for (int c : num) { System.out.print(c + " "); }
*/
}
// 遍历寻找一对括号,计算括号内的值
public void calculate() {
boolean loop = true;
while (loop) {
int left = 0, right = 0;
for (int i = 0; i < length; i++) {
if (!isEmpty[i] && fuhao[i] == '(') {
left = i;
} else if (!isEmpty[i] && fuhao[i] == ')') {
right = i;
break;
}
}
// 没有括号了,直接遍历计算
if (left == 0 && right == 0) {
calculate_third(0, length - 1);
loop = false;// 结束循环
} else {
calculate_second(left, right);//还有括号的情况
}
}
}
// 计算括号内的值,赋给左括号右边的空,后边直到右括号,全部赋为isEmpty=true
private void calculate_second(int left, int right) {
calculate_third(left + 1, right - 1);
isEmpty[left] = true;
isEmpty[right] = true;
}
// 直接计算
private void calculate_third(int m, int n) {
int num1 = 0;// 符号左边的数字
int no1 = 0;
int num2 = 0;// 符号右边的数字
int no2 = 0;
for (int i = m; i <= n; i++)// 遍历算完所有乘除法
{
if (!isEmpty[i] && (fuhao[i] == '*' || fuhao[i] == '/')) {
for (int temp1 = m; temp1 < i; temp1++) {
if (!isEmpty[temp1]
&& fuhao[temp1] != '+'
&& fuhao[temp1] != '-'
&& fuhao[temp1] != '*'
&& fuhao[temp1] != '/')// 找到乘号或除号左边的数
{
num1 = num[temp1];
no1 = temp1;
}
}
for (int temp2 = i + 1; temp2 <= n; temp2++) {
if (!isEmpty[temp2]
&& fuhao[temp2] != '+'
&& fuhao[temp2] != '-'
&& fuhao[temp2] != '*'
&& fuhao[temp2] != '/')// 找到符号右边第一个数
{
num2 = num[temp2];
no2 = temp2;
break;// 只要找到一个
}
}
if (fuhao[i] == '*') {
num[no1] = num1 * num2;
} else if (fuhao[i] == '/') {
num[no1] = num1 / num2;
}
DeletToTure(no1 + 1, no2);
}
}
for (int i = m; i <= n; i++)// 遍历算完所有加减法
{
if (!isEmpty[i] && (fuhao[i] == '+' || fuhao[i] == '-')) {
for (int temp1 = m; temp1 < i; temp1++) {
if (!isEmpty[temp1]
&& fuhao[temp1] != '+'
&& fuhao[temp1] != '-'
&& fuhao[temp1] != '*'
&& fuhao[temp1] != '/')
{
num1 = num[temp1];
no1 = temp1;
}
}
for (int temp2 = i + 1; temp2 <= n; temp2++) {
if (!isEmpty[temp2]
&& fuhao[temp2] != '+'
&& fuhao[temp2] != '-'
&& fuhao[temp2] != '*'
&& fuhao[temp2] != '/')
{
num2 = num[temp2];
no2 = temp2;
break;
}
}
if (fuhao[i] == '+') {
num[no1] = num1 + num2;
} else if (fuhao[i] == '-') {
num[no1] = num1 - num2;
}
DeletToTure(no1 + 1, no2);
}
}
}
private void DeletToTure(int i, int j) {
for (; i <= j; i++) {
isEmpty[i] = true;
}
}
public void sysout() {
for (int i = 0; i < length; i++) {
if (!isEmpty[i]) {
System.out.println(num[i]);
}
}
}
}
public class BiaoDaShiJiSuan {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String getin = sc.nextLine();
getin = getin + "#";// 结束标记
// 初始化
characterNum n = new characterNum(getin.length());
// 结构化
n.structured(getin);
// 计算
n.calculate();
// 输出
n.sysout();
sc.close();
}
}
没有采用栈结构,将中序转为后序的算法
而是自己用了三个数组,依次存储数字,符号,标记(是否为空)
例:9+44*(8-2/1)
num:[9, ,44, , , ,8, ,2, ,1, ]
fuhao:[ ,+, , ,*,(, ,-, ,/, ,)]
isEmpty:[false,false,false,true,false,false,false,false,false,false,false]
总长度为字符串长度
1.第一步将字符串结构化成三个数组
2.第二步遍历符号数组,寻找一对括号
3.计算括号内的值,赋给左括号右边的位置,左右括号标记为空,括号内除第一个位置外也标记为空
num:[9, ,44, , , ,6, ,2, ,1, ]
fuhao:[ ,+, , ,*,(, ,-, ,/, ,)]
isEmpty:[false,false,false,true,false,true,false,true,true,true,true]
4. 继续遍历,直到没有括号,就直接计算
结果
9+44*(8-2/1)
273
第一次用markdown编辑器。。。。