栈是一个陷入后出的有序列表。
栈只能在表的一端进行添加和删除,不可对另一端进行操作,也不可在中间进行插入操作。
栈的可进行添加删除操作的一端被称为栈顶,另一端成为栈底。
栈有两种基本操作:出栈(pop)、入栈(push)
栈有两种基本的实现方式:数组、链表。
以下程序使用的是数组的实现方式:
public class SimpleStackDemo {
public static void main(String[] args) {
Stack s = new Stack(5);
s.push(0);
s.push(1);
s.push(2);
s.push(3);
s.push(4);
s.printStack();
s.push(5);
s.pop();
s.pop();
s.printStack();
s.pop();
s.pop();
s.pop();
s.pop();
}
}
class Stack {
private int[] stack = null;
private int size;
private int top = -1;
public Stack(int size) {
stack = new int[size];
this.size = size;
}
/**
* 判断栈是否为空
*/
public boolean isEmpty() {
return top == -1;
}
/**
* 判断栈是否满
*/
public boolean isFull() {
return top == size - 1;
}
/**
* 添加操作
*/
public void push(int data) {
if(isFull()) {
System.out.println("栈已满,不能添加新元素");
return;
}
top++;
stack[top] = data;
}
/**
* 弹出栈
*/
public int pop() {
if(isEmpty()) {
throw new RuntimeException("栈为空,无法弹出元素");
}
int val = stack[top];
top--;
return val;
}
/**
* 打印栈
*/
public void printStack() {
if(isEmpty()) {
System.out.println("栈空间为空");
return;
}
for(int i = top; i >= 0; i--) {
System.out.printf("stack[%d]=%d\n", i, stack[i]);
}
}
}
public class StackDemo {
public static void main(String[] args) {
String str = "10+20 *8/4-2 =";
System.out.println("结果为:" + computer(str));
}
/**
* 获得综合公式的值
*/
public static int computer(String formula) {
//去除空格
formula = formula.replace(" ", "");
//去除等号
if(formula.charAt(formula.length() - 1) == '=') {
formula = formula.substring(0, formula.length() - 1);
}
Stack oprStack = new Stack(10);
Stack numStack = new Stack(11);
int index = 0;
String str = "";
while(index < formula.length()) {
char ch = formula.charAt(index);
System.out.println("本次遍历中ch为: " + ch);
if(isOpr(ch)) {// 是运算符
//如果运算符栈中已有运算符,比较添加的运算符与原来的运算符的优先级,新的运算符优先级小于原来的优先级的话,弹出数栈的两个数字,弹出操作符栈的一个运算符,
//进行计算,然后将结果压入数栈,将新的运算符放入操作符栈
if(oprStack.isEmpty()) {
oprStack.push(charToNum(ch));
index++;
continue;
}
while(priority(ch) < priority(numToChar(oprStack.peek()))) {
int num1 = numStack.pop();
int num2 = numStack.pop();
int opr = oprStack.pop();
int result = singleComputer(num1, num2, opr);
numStack.push(result);
}
oprStack.push(charToNum(ch));
index++;
} else {// 不是运算符
// 数字可能是多位数,获取多位数字
while(!isOpr(ch)) {
str += ch;
System.out.println("str值为:" + str);
// 当index指向公式 字符串最后一位时,直接跳出,不在判断下一位是否是数字
if(index >= formula.length() - 1) {
index++;
break;
}
index++;
ch = formula.charAt(index);
}
int num = Integer.parseInt(str);
numStack.push(num);
str = "";
}
}
System.out.println("数栈:");
numStack.printStack();
System.out.println("操作符栈:");
oprStack.printStack();
while(!oprStack.isEmpty()) {
int num1 = numStack.pop();
int num2 = numStack.pop();
int opr = oprStack.pop();
int result = singleComputer(num1, num2, opr);
numStack.push(result);
}
return numStack.pop();
}
/**
* 判断是否是运算符
* @param ch
* @return
*/
public static boolean isOpr(char ch) {
if(ch == '*' || ch == '/' || ch == '+' || ch =='-') {
return true;
}
return false;
}
/**
* 获取运算符的优先级
*/
public static int priority(char ch) {
if(ch == '*' || ch == '/') {
return 1;
}
if(ch == '+' || ch == '-') {
return 0;
}
return -1;
}
/**
* 将运算符转换为数字
*/
public static int charToNum(char opr) {
switch (opr) {
case '+':
return 0;
case '-':
return 1;
case '*':
return 2;
case '/':
return 3;
default:
return -1;
}
}
/**
* 将数字转换为字符
*/
public static char numToChar(int num) {
switch (num) {
case 0:
return '+';
case 1:
return '-';
case 2:
return '*';
case 3:
return '/';
default:
throw new RuntimeException("传入参数错误!");
}
}
/**
* 进行单步运算
*/
public static int singleComputer(int num1, int num2, int opr) {
switch (opr) {
case 0:
return num1 + num2;
case 1:
return num2 - num1;
case 2:
return num1 * num2;
case 3:
return num2 / num1;
default:
throw new RuntimeException("传参错误,单步计算错误");
}
}
}
class Stack {
private int[] stack = null;
private int size;
private int top = -1;
public Stack(int size) {
stack = new int[size];
this.size = size;
}
/**
* 判断栈是否为空
*/
public boolean isEmpty() {
return top == -1;
}
/**
* 判断栈是否满
*/
public boolean isFull() {
return top == size - 1;
}
/**
* 添加操作
*/
public void push(int data) {
if(isFull()) {
System.out.println("栈已满,不能添加新元素");
return;
}
top++;
stack[top] = data;
}
/**
* 弹出栈
*/
public int pop() {
if(isEmpty()) {
throw new RuntimeException("栈为空,无法弹出元素");
}
int val = stack[top];
top--;
return val;
}
/**
* 读取栈顶元素,但不弹出
*/
public int peek() {
if(isEmpty()) {
throw new RuntimeException("栈为空,无法读取栈顶元素");
}
return stack[top];
}
/**
* 打印栈
*/
public void printStack() {
if(isEmpty()) {
System.out.println("栈空间为空");
return;
}
for(int i = top; i >= 0; i--) {
System.out.printf("stack[%d]=%d\n", i, stack[i]);
}
}
}
前缀表达式
前缀表达式又叫做波兰表达式。前缀表达式是一种没有括号算术的表达式,其将运算符写在前面,将操作数写在后面。
中缀表达式
中缀表达式就是常见的运算表达式。
后缀表达式
后缀表达式又称逆波兰表达式,与前缀表达式相似,只是运算符位于操作数之后。
前缀表达式
中缀表达式
后缀表达式
中缀表达式转换为前缀表达式
1+((2+3)*4)-5
====》 - + 1 * + 2 3 4 5
中缀表达式转换为后缀表达式
1+((2+3)*4)-5
====》1 2 3 + 4 * + 5 -
以下程序为中缀表达式转换为后缀表达式,并对后缀表达式求值:
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
/**
* 中缀表达式转换为后缀表达式,并进行计算
*
*/
public class Test {
public static void main(String[] args) {
String str = "1+((2+3)*4)-5";
List<String> list = strToList(str);
System.out.println(list);
List<String> suf = infixToSuffix(list);
System.out.println(suf);
int res = calculation(suf);
System.out.println("结果为:" + res);
}
/**
* 将综合公式字符串转换为ArrayList
*/
public static List<String> strToList(String str) {
if("".equals(str.trim()) || str == null) {
throw new RuntimeException("综合表达式输入错误!");
}
List<String> list = new ArrayList<>();
for(int i = 0; i < str.length(); i++) {
char ch = str.charAt(i);
String s = "";
// 根据ASCII, ch为数字
if(ch >= 48 && ch <= 57) {
while(ch >= 48 && ch <= 57) {
s += ch;
//如果是字符串最后一个字符,则不再 i++
if(i == str.length() -1) {
break;
}
i++;
ch = str.charAt(i);
}
list.add(s);
// 当因为i为最后一个时,跳出循环,不在i--,
if(i != str.length() -1) {
i--;
}
} else {
list.add("" + ch);
}
}
return list;
}
/**
* 中缀表达式转换为后缀表达式
*/
public static List<String> infixToSuffix(List<String> list) {
if(list == null || list.size() == 0) {
throw new RuntimeException("参数输入错误!");
}
Stack<String> s1 = new Stack<String>();
List<String> s2 = new ArrayList<String>();
for(String str : list) {
if(str.matches("\\d+")) { // 判断是数字
s2.add(str);
} else if("(".equals(str)) {
s1.push(str);
} else if(")".equals(str)) {
String s = "";
while(true) {
s = s1.pop();
if("(".equals(s)) {
break;
} else {
s2.add(s);
}
}
} else {// 是运算符:+ - * /
if(s1.isEmpty() || "(".equals(s1.peek())) {
s1.push(str);
} else if(priority(str) > priority(s1.peek())) {
s1.push(str);
} else {
while(!s1.isEmpty() && !"(".equals(s1.peek())) {
s2.add(s1.pop());
}
s1.push(str);
}
}
}
while(!s1.isEmpty()) {
s2.add(s1.pop());
}
return s2;
}
/**
* 后缀表达式的计算
*/
public static int calculation(List<String> list) {
if(list.isEmpty() || list == null) {
throw new RuntimeException("传参错误!");
}
Stack<Integer> stack = new Stack<>();
for(String str : list) {
if(str.matches("\\d+")) {
stack.push(Integer.parseInt(str));
} else {
int num2 = stack.pop();
int num1 = stack.pop();
if("+".equals(str)) {
stack.push(num1 + num2);
}else if("-".equals(str)) {
stack.push(num1 - num2);
}else if("*".equals(str)) {
stack.push(num1 * num2);
}else if("/".equals(str)) {
stack.push(num1 / num2);
}
}
}
return stack.pop();
}
/**
* 判断优先级
*/
public static int priority(String str) {
if("+".equals(str) || "-".equals(str)) {
return 1;
} else if("*".equals(str) || "/".equals(str)) {
return 2;
} else {
throw new RuntimeException("参数输入错误!");
}
}
}