栈简介
栈是一个先入后出(FILO)的有序列表,最先放入的数据在栈底,最后放入的元素在栈顶,最后放入的元素先删除,最先放入的先删除。
栈的实现
public class Stack {
private int[] stack;
private int top;
private int maxSize;
public Stack(int maxSize){
this.stack=new int[maxSize];
this.maxSize=maxSize;
this.top=0;
}
public boolean isFull(){
return top==maxSize;
}
public boolean isEmpty(){
return top==0;
}
public boolean push(int value){
if(isFull()) return false;
this.stack[top]=value;
top++;
return true;
}
public Integer pop(){
if(isEmpty()) return null;
int value=stack[top];
top--;
return value;
}
}
中缀表达式的计算
算法思路
比如计算:3+2*6-2
算法步骤如下:
维护2个栈数字栈和符号栈
- 从前往后扫描如果遇到数字,直接入数字栈。
- 如果遇到符号分为以下3种情况:
- 如果符号栈为空,直接入栈。
- 如果符号栈不为空且符号优先级小于或等于栈顶元素,那么pop出两个数字运算,然后将结果重新入栈。
- 如果符号栈不为空且符号优先级大于栈顶元素,符号直接入栈
代码实现
牛客网地址:https://www.nowcoder.com/questionTerminal/7b18aa6b7cc14f8eaae6b8acdebf890b?toCommentId=103161
import java.util.Scanner;
import java.util.Stack;
public class Main {
public static void main(String[] args) throws Exception {
Scanner cin = new Scanner(System.in);
Main m=new Main();
while (cin.hasNext()){
String exp=cin.next();
float res=m.nifix(exp);
System.out.println((int)res);
}
}
public float nifix(String expression){
Stack<Float> numberStack=new Stack<>();
Stack<Character> symbolStack=new Stack<>();
String digit="";
for(int i=0;i<expression.length();i++){
char x=expression.charAt(i);
if(Character.isDigit(x)){
digit+=String.valueOf(x);
if(i+1>=expression.length()||!Character.isDigit(expression.charAt(i+1))){
numberStack.push(Float.parseFloat(digit));
digit="";
}
}else {
while (!symbolStack.isEmpty()&&priority(symbolStack.peek())>=priority(x)){
char y=symbolStack.pop();
float res=calRes(y,numberStack.pop(),numberStack.pop());
numberStack.push(res);
}
symbolStack.push(x);
}
}
while (!symbolStack.isEmpty()){
char y=symbolStack.pop();
float res=calRes(y,numberStack.pop(),numberStack.pop());
numberStack.push(res);
}
return numberStack.pop();
}
//判断符号的优先级
private int priority(char x){
if(x =='+'|| x =='-'){
return 1;
}else{
return 2;
}
}
//计算结果
private float calRes(char x,float num1,float num2){
float res=0;
switch (x){
case '+':
res=num1+num2;
break;
case '-':
res=num2-num1;
break;
case '*':
res=num1*num2;
break;
case '/':
res=num2/num1;
break;
}
return res;
}
}
后缀表达式的计算
算法思路
后缀表达式的例子:
(3+4)x5-6对应的后缀表达式就是34+5x6-。
计算机处理后缀表达式是很直接的,维护一个栈就可以完成计算。
代码实现
import java.util.Scanner;
import java.util.Stack;
public class Main {
public static void main(String[] args) throws Exception {
Scanner cin = new Scanner(System.in);
Main m=new Main();
while (cin.hasNext()){
String exp=cin.next();
float res=m.postfix(exp);
System.out.println((int)res);
}
}
public float postfix(String expression){
String[] expressionItem=expression.split(" ");
Stack<Float> stack=new Stack<>();
for(int i=0;i<expressionItem.length;i++){
String item=expressionItem[i];
if(isNumeric(item)){
stack.push(Float.parseFloat(item));
}else {
stack.push(cal(item,stack.pop(),stack.pop()));
}
}
return stack.pop();
}
private static boolean isNumeric(String str){
for (int i = str.length();--i>=0;){
if (!Character.isDigit(str.charAt(i))){
return false;
}
}
return true;
}
//计算结果
private float cal(String item,float num1,float num2){
float res=0;
if(item.equals("+")){
res=num2+num1;
}else if(item.equals("-")){
res=num2-num1;
}else if(item.equals("/")){
res=num2/num1;
}else if(item.equals("*")){
res=num2*num1;
}
return res;
}
}
中缀表达式转后缀表达式
限制必须是1位数
输入:
a+bc/d-a+f/b
输出:
abcd/+a-fb/+
算法思路
- 从左到右开始扫描中缀表达式
- 遇到数字时,加入后缀表达式
- 遇到运算符时:
a.若为’(’,入栈
b.若为’)’,则依次将栈中的运算符加入到后缀表达式中,直到出现’(‘为止,从栈中删除’(’
c.若为除括号外的其它运算符,当优先级高于除’('以外的栈顶运算符时,直接入栈;否则从栈顶开始,依次弹出比当前处理的运算符优先级高和优先级相等的运算符,直到出现一个比它优先级低或者遇到了一个左括号为止。
代码实现
import java.util.Scanner;
import java.util.Stack;
public class Main {
public static void main(String[] args) throws Exception {
Scanner cin = new Scanner(System.in);
Main m = new Main();
while (cin.hasNext()) {
String exp = cin.next();
String res = m.niToPost(exp);
System.out.println(res);
}
}
//判断是否是数字
private static boolean isNumeric(char c) {
if (c == '+' || c == '-' || c == '*' || c == '/' || c == '(' || c == ')')
return false;
return true;
}
public String niToPost(String expression) {
char[] res = new char[expression.length()];
int index = 0;
Stack<Character> symbolStack = new Stack<>();
for (int i = 0; i < expression.length(); i++) {
char x = expression.charAt(i);
if (isNumeric(x)) {
res[index] = x;
index++;
} else if (x == '(') {
symbolStack.push(x);
} else if (x == ')') {
while (symbolStack.peek() != '(') {
res[index] = symbolStack.pop();
index++;
}
symbolStack.pop();
} else {
while (!symbolStack.isEmpty() && symbolStack.peek() != '(' && priority(symbolStack.peek()) >= priority(x)) {
res[index] = symbolStack.pop();
index++;
}
symbolStack.push(x);
}
}
while (!symbolStack.isEmpty()) {
res[index] = symbolStack.pop();
index++;
}
return String.valueOf(res);
}
//判断符号的优先级
private int priority(char x) {
if (x == '+' || x == '-') {
return 1;
} else if (x == '*' || x == '/') {
return 2;
}
return 0;
}
}