第一部分,仅实现简单计算功能,复杂运算会在后续完善。仅实现像3+5*9-2+7这样的运算。
2021.4.14更新,第二部分:后缀表达式可完成多位数及括号运算
预告,中缀表达式转后缀表达式
思路
来源于尚硅谷课堂
2021.4.11修改,可以计算多位数,并修改了一个小Bug
package Stack;
public class computstack {
public static void main(String[] args) {
// TODO Auto-generated method stub
/*包含功能(public)
* 1.构造器
* 2.判断栈空
* 3.判断栈满
* 4.遍历栈
* 5.入栈
* 6.出栈
* 7.判断符号优先级
* 8.判断读取元素是数字还是字符
* 9.计算相操作结果
* 10.显示栈顶元素(计算时调用)
* */
//测试
//创建数字栈和符号栈,分别存放数字和字符
ArrayComputStackLinked numstack = new ArrayComputStackLinked(10);
ArrayComputStackLinked chstack = new ArrayComputStackLinked(10);
//定义字符串并定义辅助指针遍历
String expression = "20-10+5*4";//30
//定义相关变量
int num1 = 0; //算数1
int num2 = 0; //算数2
int ch; //操作符
int index = 0; //辅助指针
int res = 0; //运算结果
char chch = ' ';//暂存运算符
String sumnums = "";//连接多位数
//开始扫描字符串将结果分别导入两个栈中
while(true) {
//取出一位且步长为1,构成字符串,然后取出字符串的第0位
chch = expression.substring(index,index+1).charAt(0);//[0,1)
//取出chch后判断什么形式
if(chstack.judge(chch)) {
//若为字符串
if(!chstack.emptystack()) {
//若符号栈不为空,比较与栈中字符的优先级,若优先级高则直接入栈,若优先级第则取出原先的字符参与运算,最后入栈
if(chstack.priority(chch)>chstack.priority(chstack.peek())) {
//优先级较高,直接入栈
chstack.push(chch);
}else {
//优先级较低,出栈一位运算
num1 = numstack.pop();//出一位数字
num2 = numstack.pop();//出一位数字
ch = chstack.pop(); //出一位符号
res = numstack.operation(num1,num2,ch);
numstack.push(res);
chstack.push(chch);
}
}else {
//栈为空
chstack.push(chch);
}
}else {
//取出元素为数字
//numstack.push(chch-'0');//chch-48
//判断数字位数并取出存入数栈
sumnums+=chch;
if(index == expression.length()-1) {
numstack.push(Integer.parseInt(sumnums));//最后一位时数字入数栈
}else {
if(chstack.judge(expression.substring(index+1,index+2).charAt(0))) {//???
//若元素的后一位时字符,则可以入数栈
numstack.push(Integer.parseInt(sumnums));//合并好的数字入数栈
sumnums = "";//清空,为下次做准备
}
}
}
index++;
if(index >=expression.length()) {
break;
}
}
//遍历完毕,剩余元素运算后入数栈
while(true) {
if(chstack.emptystack()) {
break;//字符栈为空表示运算完毕,数栈中为结果
}else {
num1 = numstack.pop();
num2 = numstack.pop();
ch = chstack.pop();
res = numstack.operation(num1,num2,ch);
numstack.push(res);
}
}
//结束后数栈只剩结果
System.out.printf("表达式%s的运算结果为%d\n",expression,numstack.peek());//numstack.pop()
}
}
class ArrayComputStackLinked{
private int top = -1; //栈顶
private int[]stack; //定义数组栈
private int MaxTop; //定义栈的大小
//创建构造器
public ArrayComputStackLinked(int maxtop) {
this.MaxTop = maxtop; //传入栈的大小
stack = new int[this.MaxTop]; //创建栈,大小等于输入
}
/*开始创建操作函数*/
//判断栈空
public boolean emptystack() {
return top == -1;
}
//判断栈满
public boolean isfullstack() {
return top == MaxTop-1; //???
}
//遍历栈
public void liststack() {
//考虑栈空时无法遍历
if(emptystack()) {
System.out.println("栈空,无法遍历");
return;
}
//栈中数值正常时
for(int i = top;i>=0;i--) {
System.out.printf("stack[%d] = %d\n",i,stack[i]);
}
}
//入栈操作
public void push(int value) {
//判断栈是否满
if(isfullstack()) {
System.out.println("栈满,无法入栈");
return;
}
//栈不满时
top++;
stack[top] = value;
}
//出栈
public int pop() {
//栈空
if(emptystack()) {
// System.out.println("栈空,无法出栈");
// return 0;
//抛出异常
throw new RuntimeException("栈空,没有数据");
}
//栈非空时
int value = stack[top];
top--;
return value;
}
//定义功能:判断符号优先级
public int priority(int ch) {
if(ch == '*' || ch == '/') {
return 1;
}else if(ch == '+' || ch == '-') {
return 0;
}else {
return -1;
}
}
//定义功能判断指向的是数字还是字符:利用布尔变量
public boolean judge(char ch) {
return ch == '-' || ch=='+' || ch =='*' || ch =='/';
//出现符号时返回真值
}
//运算模块:完成符号+数字运算(数字1,数字2,运算字符)
public int operation(int num1,int num2,int ch) { //int和cahr通用
int num = 0;//暂存运算结果
switch(ch) {
case '+':
num = num1+num2;
break;
case '-':
num = num2-num1;//num2为后出先进数字
break;
case '*':
num = num1*num2;
break;
case '/':
num = num2/num1;
break;
default:
break;
}
//最后返回运算结果
return num;
}
//显示栈顶元素(不取出)
public int peek() {
return stack[top];
}
}
利用逆波兰表达式计算
package Poland;
import java.util.List;
import java.util.Stack;
import java.util.ArrayList;
public class Polandcomputer {
public static void main(String[] args) {
// TODO Auto-generated method stub
/*逆波兰表达式计算器
* 后缀表达式:34+5*6-
* 中缀表达式:(3+4)*5-6
* 思路:将中缀表达式转化为后缀表达式,然后读取进list集合中
* 最后从list中读取元素并计算
* */
String Postfixexpression = "30 4 + 5 * 6 -";//创建字符串
List<String> rpnList = getListString(Postfixexpression);
System.out.println("rpnList" + rpnList);
int result = computer(rpnList);
System.out.println("计算结果="+result);
}
//将逆波兰表达式一次读入数组中ArrayList
public static List<String> getListString(String Postfixexpression){//定义方法,输入字符串
//将Postfixexpression分割
String[] split = Postfixexpression.split(" ");//返回一个数组
//System.out.println(split);
List<String> list = new ArrayList<String>();//创建新列表list
for(String ele:split) {//for循环增强
list.add(ele);
}
return list;
}
public static int computer(List<String> ch) {
//创建栈
Stack<String> stack = new Stack<String>();
//遍历ch
for(String item:ch) {
//正则表达式取出数
if(item.matches("\\d+")) {//匹配多位数
stack.push(item);
}else {
int num2 = Integer.parseInt(stack.pop());
int num1 = Integer.parseInt(stack.pop());
int result = 0;
if(item.equals("+")) {
result = num1+num2;
}else if(item.equals("-")) {
result = num1-num2;
}else if(item.equals("*")) {
result = num1*num2;
}else if(item.equals("/")) {
result = num1/num2;
}else {
throw new RuntimeException("运算符有误");
}
stack.push(""+result);
}
}
return Integer.parseInt(stack.pop());
}
}