这里栈用的是链式存储,首先将输入的前缀表达式转换为后缀表达式,然后求值。本来还想实现多位数和括号的表达式求值,但是写了一个多小时,总是报错,就先实现简单的吧。
- 堆栈的链式结构存储实现:
//节点的代码
public class Node {
public int data;
public Node next; //指向下一个节点
public Node() {
}
public Node(int value) {
this.data = value;
}
@Override
public String toString() {
return "HeroNode{" +
"num=" + data +
'}';
}
}
//实现链栈的代码
public class LinkedStack {
//栈顶指针top
Node top;
//创建一个栈,栈顶指针top初始化为链表的头节点
public LinkedStack() {
top = new Node();
}
//判断栈是否为空
public boolean isEmpty() {
return top.next == null;
}
//入栈操作
public void push(int value) {
//申请一个新的节点
Node temp = new Node();
//将要插入的数据放入新的节点的data域中
temp.data = value;
//执行节点的插入操作
temp.next = top.next;
top.next = temp;
}
//出栈操作
public int pop() {
//定义一个临时变量,用来指向栈顶的第一个节点,即:top指针的下一个指针
Node temp = top.next;
if (isEmpty()) {
throw new RuntimeException("栈空,不能出栈!");
}
top.next = temp.next;
return temp.data;
}
//遍历并显示链栈中的元素
public void showStack() {
//定义一个临时变量,用来指向栈顶的节点,即:top指针的下一个指针
Node temp = top.next;
if (isEmpty()) {
System.out.println("链栈为空!");
return;
}
while (temp != null) {
System.out.println(temp.data);
temp = temp.next;
}
}
//获取栈顶的元素但是不出栈
public int getTop() {
if (!isEmpty()) {
return top.next.data;
}else {
return 0;
}
}
}
- 具体表达式求值代码:
public static void main(String[] args) {
//用来存放数据的栈
LinkedStack valueStack = new LinkedStack();
//用来存放操作符的栈
LinkedStack symStack = new LinkedStack();
//用来遍历表达式的索引变量
int index=0;
//是否扫描完了字符串的标志
boolean sign = false;
//从键盘输入表达式
Scanner sc = new Scanner(System.in);
//接收从键盘输入的表达式字符串
String str = sc.next();
//将字符串表达式中的数据和运算符存入数组中,方便遍历
char[] array = str.toCharArray();
//开始遍历字符串表达式
while (true) {
//还没遍历完表达式
if (index < array.length) {
//判断是否是数字
if (!judge(array[index])) {
//是数字就直接入栈
valueStack.push(array[index]-'0');
}else if (judge(array[index])) { //判断是否为运算符
//判断存放运算符的栈是否为空
if(symStack.isEmpty()) {
//如果为空,则直接将运算符入栈
symStack.push(array[index]);
}else {
//获取到符号栈中栈顶的运算符
int temp;
temp = symStack.top.next.data;
//如果不为空,则比较运算符的优先级
if (priority(array[index]) > priority(temp)) {
//如果当前运算符的优先级大于栈中运算符的优先级,直接入栈
symStack.push(array[index]);
}else {
while (priority(array[index]) <= priority(symStack.getTop())) {
if (!symStack.isEmpty()) {
//如果当前运算符的优先级小于栈顶运算符的优先级时,将符号栈中的栈顶运算符出栈,直到当前运算符的优先级大于栈顶运算符的优先级为止
//用一个临时变量存储计算的结果
int result;
//数字栈中出栈2个元素用符号栈中出栈的符号进行运算
result = calc(valueStack.pop(), valueStack.pop(), symStack.pop());
//在将计算的结果存入数字栈中,以用于下次的运算
valueStack.push(result);
}else {
break;
}
}
//如果当前运算符的优先级大于栈顶运算符的优先级时,将当前运算符入栈
symStack.push(array[index]);
}
}
}
index++;
}else {
//已经遍历完了表达式
sign = true;
break;
}
}
// //遍历完字符串表达式
//顺序将数字栈和符号栈中出栈相应的数和符号
while (true) {
if (valueStack.top.next.next == null) {
break;
}
//如果数字栈中只剩一个元素了,那它就是表达式的结果,最后直接出栈即可
//用一个临时变量存储计算的结果
int res;
//数字栈中出栈2个元素用符号栈中出栈的符号进行运算
res = calc(valueStack.pop(), valueStack.pop(), symStack.pop());
//在将计算的结果存入数字栈中,以用于下次的运算
valueStack.push(res);
}
//将表达式的结果显示出来
valueStack.showStack();
}
//判断是不是运算符
public static boolean judge(int value) {
boolean sign;
if (value == '*' || value == '/' || value == '+' || value == '-') {
sign = true;
}else {
sign = false;
}
return sign;
}
//定义一个判断运算符优先级的方法
//用返回值的大小来定义优先级
public static int priority(int sym) {
int result;
if(sym == '*' || sym == '/') {
result = 1;
}else if(sym == '+' || sym == '-') {
result = 0;
}else {
result = -1;
}
return result;
}
//定义一个计算的方法
public static int calc(int a,int b ,int sym) throws ArithmeticException {
//用于存放计算的结果
int r = 0;
switch (sym) {
case '*':
r = a * b;
break;
case '/':
r = b/a;
break;
case '+':
r = a + b;
break;
case '-':
r = b-a;
break;
default:
break;
}
return r;
}