java栈多位数表达式计算_用栈实现多项式的计算(java语言实现)

基本思路:

(1)通过一个index值作为索引(int类型),来遍历多项式;

(2)如果扫描到一个数字,就直接入数栈;

(3)如果扫描到一个符号,就分以下情况:

a、如果当前符号栈为空,就将该符号直接入符号栈;

b、如果符号栈不为空,就要进行优先级的比较:

1、如果 当前扫描到的操作符 的优先级 小于或等于 栈顶的操作符,就要从 数栈 中 pop 出两个数,同时从 符号栈 中 pop 出一个符号,构成运算式进行运算。运算得到的结果入数栈,然后再将 当前扫描到的操作符 入符号栈

2、如果 当前扫描到的操作符 的优先级 大于 栈顶的操作符,就直接入符号栈。

(4)当多项式扫描完毕时,就依次从 数栈 和符号栈 中 pop 出相应的数和符号(每一轮pop出 2个数和1个符号 ,组成一个运算式进行运算,将运算结果 压入数栈),循环往复。

(5)最后,符号栈会空,数栈中留下最后一个数,该数即为运算结果。

首先创建一个数组栈,实现基本的操作如下:

// 定义一个ArrayStack 表示栈

class ArrayStackCul {

private int maxSize; // 栈的最大容量

private int[] stack; // 数组模拟栈,数据放在该数组中

private int top = -1;//栈顶指针

// 构造器

public ArrayStackCul(int maxSize) {

this.maxSize = maxSize;

stack = new int[this.maxSize];

}

// 判断栈满

public boolean isFull() {

return top == maxSize - 1;

}

// 判断栈空

public boolean isEmpty() {

return top == -1;

}

// 入栈

public void push(int value) {

// 入栈前先判断栈是否满

if (isFull()) {

System.out.println("栈满!");

return;

}

top++;

stack[top] = value;

}

// 出栈

public int pop() {

// 出栈前,先判断栈是否空

if (isEmpty()) {

// 由于必须要返回值,所以用抛出异常来处理

throw new RuntimeException("栈空,没有数据~");

}

int value = stack[top];

top--;

return value;

}

// 栈的遍历(只能从栈顶往下遍历)

public void list() {

if (isEmpty()) {

System.out.println("没有数据,无法遍历");

return;

}

for (int i = top; i >= 0; i--) {

System.out.printf("stack[%d] = %d\n", i, stack[i]);

}

}

}

为了实现多项式运算,还要为该栈功能进行拓展:

(1)为了比较扫描串中 当前扫描的运算符 和 栈顶运算符 的优先级,定义peek()方法,直接返回 栈顶的元素值,但不取出;

(2)比较运算符优先级的前提是定义和返回优先级,故定义priority(char oper)方法,用于返回操作符oper的优先级;

(3)因为多项式中既有操作符又有数字,为了方便区分,定义isOper(char)方法,用于判断该符号是否是操作符;

(4)定义一个cal(int num1,  int num2 , char oper)方法,根据oper运算符的不同,实现不同运算式的统一计算。

// 为了实现运算器的功能,需拓展功能:

/*

* 返回运算符的优先级,优先级由程序员来确定,用数字来表示 默认:数字越大,优先级越高

*/

/*

* 为了将扫描串中的运算符与栈顶运算符进行比较 定义一个方法,直接返回栈顶的元素值,但不取出

*/

//该方法用于查看栈顶元素

public int peek() {

return stack[top];

}

// 该方法用于返回元素的优先级

// 在java中int 和 char 是可以比较的

public int priority(int oper) {

if (oper == '*' || oper == '/') {

return 1;

} else if (oper == '+' || oper == '-') {

return 0;

} else {

return -1; // 以上定义是假设目前表达式只有+ - * / 四种运算

}

}

// 判断当前扫描的符号是不是一个运算符

// 本方法的目的是方便直接区分“运算符”与“数字”

public boolean isOper(char val) {

return val == '+' || val == '-' || val == '*' || val == '/';

}// 在当前情景下,不是运算符当然就只能是数字了

//此方法用于计算出栈元素构成运算式的运算结果

// num1比num2先出栈,oper为运算符

public int cal(int num1, int num2, int oper) {

int res = 0;// res用来存放运算的结果

switch (oper) {

case '+':

res = num2 + num1;

break;

case '-':

res = num2 - num1;

break;

case '*':

res = num2 * num1;

break;

case '/':

res = num2 / num1;

break;

default:

System.out.println("符号有误。");

break;

}

return res;

}

最后在main函数中实现开头的思路:(难点)注释详细

package Stack;

public class Calculator {

public static void main(String[] args) {

// 根据前面的思路,完成表达式的运算

String expression = "70+20*6-20/4"; // 如何处理多位数的问题?

// 创建两个栈,一个数栈,一个符号栈

ArrayStackCul numStack = new ArrayStackCul(10);

ArrayStackCul operStack = new ArrayStackCul(10);

// 创建需要的变量

int index = 0;// 用于扫描

char ch = ' ';// 扫描到的结果存储在ch里面,进行下一步的判断

int num1;

int num2;

int oper;// num1为先出栈数据

int res;// 运算结果

String keepNum = "";// 用于处理多位数运算问题(难点),该变量用来存储一个多位数

while (true) {

// 开始扫描

ch = expression.substring(index, index + 1).charAt(0);

// subString指的是取一个子串;charAt(0)表示取子串的第一个字符

if (operStack.isOper(ch)) {// 如果是运算符

if (!operStack.isEmpty()) {

if (operStack.priority(ch) <= operStack.priority(operStack.peek())) {

// ① 扫描的当前运算符 < 栈顶运算符 ——> 执行思路1

num1 = numStack.pop();

num2 = numStack.pop();

oper = operStack.pop();

res = numStack.cal(num1, num2, oper);

// 运算出的结果入栈

numStack.push(res);

// 最后还要将当前优先级小的运算符入栈

operStack.push(ch);

} else {

// ② 当前运算符的优先级大,执行思路2

operStack.push(ch);

}

} else {// 如果当前符号栈为空,则直接入栈

operStack.push(ch);

}

} else {// 如果是数字,直接入数字栈

/*

* // numStack.push(ch);//这样写是错误的,因为我们得到的数字其实是'字符'

* numStack.push(ch - 48);//字符模式的数 与 数字模式的数 ASCII码差了48

*/

// 以上做法无法处理多位数的问题,解决多位数计算问题的思路:

/*

* 1、当处理数时,不能发现是一个数,就直接入栈 2、在处理数字时,需要想expression的表达式的index后再看一位

* 如果是数,就继续扫描;如果是运算符,则将扫描的整体转换成数值后入栈

* 3、因此需要定义一个字符串变量用于拼接(KeepNum)

*/

keepNum += ch;

// 往后试探一位index + 1 ,如果是数字,则继续扫描;如果是运算符,则入栈

// 另外如果ch已经是expression的最后一位,就直接入栈

if (index == expression.length() - 1) {

numStack.push(Integer.parseInt(keepNum));

//必须将多位数转换成一个整型数,才能参与运算

} else {

//如果没有上面这个判断,会报越界错误。

//这启发我们:对最后一位一定要慎重考虑,优化逻辑

if (operStack.isOper(expression.substring(index + 1, index + 2).charAt(0))) {

numStack.push(Integer.parseInt(keepNum));

// 十分重要!!!:必须将keepNum置为空

keepNum = "";

}

}

}

// 让index + 1 , 并判断是否扫描到expression的最后

// index只是扫描的索引,每扫描一个字符就+1,index >= 字符串长度时,表示扫描完

index++;

if (index >= expression.length()) {

break;

}

}

// 表达式扫描完毕后,

// 依次弹出两个栈中的数和符号,依次计算结果,直到符号栈空

while (true) {

// ③ 如果符号栈为空,则计算最后的结果,即数栈中的最后一个数

if (operStack.isEmpty()) {

break;

}

num1 = numStack.pop();

num2 = numStack.pop();

oper = operStack.pop();

res = numStack.cal(num1, num2, oper);

numStack.push(res);

}

// 将数栈中最后一个数pop出来,就是结果

int result = numStack.pop();

System.out.printf("表达式%s = %d", expression, result);

}

}

}

a26f92b3386b33d557a32b383bb5630d.png

4a668feaa3018a2e1706f07e5002bcc8.png

ABC出云

发布了7 篇原创文章 · 获赞 1 · 访问量 895

私信

关注

标签:oper,index,java,int,多项式,扫描,运算符,用栈,numStack

来源: https://blog.csdn.net/weixin_40389106/article/details/104071631

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值