栈 Stack
github: https://github.com/hongbao-chen/learn-java-datastuctures
一、介绍:
栈是限制插入和删除只能在一个位置操作的线性数据结构。先进后出。
压栈/入栈:push
出栈/弹栈:pop
二、栈的实现
-
栈实现 由于栈是一个表,因此任何实现表的方法都可以用来实现栈。主要有两种方式,链表实现和数组实现。 -
链表实现栈 可以使用单链表来实现栈。通过在表顶端插入一个元素来实现 PUSH,通过删除表顶端元素来实现 POP。使用链表方式实现的栈又叫动态栈。动态栈有链表的部分特性,即元素与元素之间在物理存储上可以不连续,但是功能有些受限制,动态栈只能在栈顶处进行插入和删除操作,不能在栈尾或栈中间进行插入和删除操作 -
数组实现栈 栈也可以用数组来实现。使用数组方式实现的栈叫静态栈
1.使用数组实现栈:
package com.example.stack.basic;
public class ArrayStack {
private int maxStack;
private int[] stack;
private int top = -1;
public ArrayStack(int maxStack) {
this.maxStack = maxStack;
this.stack = new int[maxStack];
}
public boolean isFull() {
return this.top == this.maxStack - 1;
}
public boolean isEmpty(){
return this.top == -1;
}
public void push(int val){
if (isFull()){
throw new RuntimeException("stack is full");
}
top++;
stack[top]=val;
}
public int pop(){
if (isEmpty()){
throw new RuntimeException("stack is empty");
}
return stack[top--];
}
public void list(){
if (isEmpty()){
throw new RuntimeException("stack is empty");
}
for (int i = 0; i < stack.length; i++) {
System.out.printf("stack[%d]=%d\n",i,stack[i]);
}
}
}
2.使用栈实现计算器: + - * /
栈:
public class ArrayStack<T> {
private int maxStack;
private T[] stack;
private int top = -1;
public ArrayStack(int maxStack) {
this.maxStack = maxStack;
this.stack = (T[]) new Object[maxStack];
}
public boolean isFull() {
return this.top == this.maxStack - 1;
}
public boolean isEmpty(){
return this.top == -1;
}
public void push(T val){
if (isFull()){
throw new RuntimeException("stack is full");
}
top++;
stack[top]=val;
}
public T pop(){
if (isEmpty()){
throw new RuntimeException("stack is empty");
}
return stack[top--];
}
public void list(){
if (isEmpty()){
throw new RuntimeException("stack is empty");
}
for (int i = 0; i < stack.length; i++) {
System.out.printf("stack[%d]=%c\n",i,stack[i]);
}
}
public T peek() {
if (isEmpty()){
throw new RuntimeException("stack is empty");
}
return stack[top];
}
}
calculate:
package com.example.stack.basic;
public class Calculate {
public static int calculate(String waitCal) {
ArrayStack<Integer> numStack = new ArrayStack<Integer>(20);
ArrayStack<Character> symbolStack = new ArrayStack<Character>(20);
String num = "";
String symbol = "";
for (int i = 0; i < waitCal.length(); i++) {
char c = waitCal.charAt(i);
if (isNum(c)) {
num = num + c;
} else if (isSymbol(c)) {
symbol = symbol + c;
numStack.push(Integer.parseInt(num));
num = "";
symbolPush(c, numStack, symbolStack);
symbol = "";
}
if( i == waitCal.length()-1){
numStack.push(Integer.parseInt(num));
num = "";
}
}
while (!symbolStack.isEmpty()){
int num1 = numStack.pop();
int num2 = numStack.pop();
int popSymbol = symbolStack.pop();
int calculate = calculate(num1, num2, popSymbol);
numStack.push(calculate);
}
return numStack.pop();
}
private static void symbolPush(char c, ArrayStack<Integer> numStack, ArrayStack<Character> symbolStack) {
if (symbolStack.isEmpty()) {
symbolStack.push(c);
return ;
}
int topVal = symbolStack.peek();
int priorityPeek = getPriority((char) topVal);
int priorityC = getPriority(c);
if (priorityC >= priorityPeek){
symbolStack.push(c);
}else {
int num1 = numStack.pop();
int num2 = numStack.pop();
int symbolTop = symbolStack.pop();
int result = calculate(num1,num2,symbolTop);
numStack.push(result);
symbolPush(c,numStack,symbolStack);
}
}
private static int calculate(int num1, int num2, int symbolTop) {
char symbol = (char)symbolTop;
return switch (symbol) {
case '+' -> num2 + num1;
case '-' -> num2 - num1;
case '*' -> num2 * num1;
case '/' -> num2 / num1;
default -> throw new RuntimeException("error symbol");
};
}
private static int getPriority(char topVal) {
return switch (topVal) {
case '+', '-' -> 0;
case '*', '/' -> 1;
default -> -1;
};
}
private static boolean isSymbol(char c) {
return switch (c) {
case '+', '-', '*', '/' -> true;
default -> false;
};
}
private static boolean isNum(char c) {
return c >= '0' && c <= '9';
}
}
测试:
package com.example.stack.basic;
public class Test {
public static void main(String[] args) {
String waitCal = "3+2*2+13";
int result = Calculate.calculate(waitCal);
System.out.printf("%s=%d",waitCal,result);
}
}
//结果:
3+2*2+13=20
3、使用栈实现计算器:+ - * / ( )
修改calculate:
package com.example.stack.improve;
import com.example.stack.basic.ArrayStack;
public class ImproveCalculate {
public static int calculate(String waitCal) {
ArrayStack<Integer> numStack = new ArrayStack<Integer>(20);
ArrayStack<Character> symbolStack = new ArrayStack<Character>(20);
String num = "";
String symbol = "";
for (int i = 0; i < waitCal.length(); i++) {
char c = waitCal.charAt(i);
if (isNum(c)) {
num = num + c;
} else if (isSymbol(c)) {
symbol = symbol + c;
if (!"".equals(num)){
numStack.push(Integer.parseInt(num));
num = "";
}
symbolPush(c, numStack, symbolStack);
symbol = "";
}else if ( isParenthesesLeft(c) ){
symbolStack.push(c);
}else if ( isParenthesesRight(c) ){
numStack.push(Integer.parseInt(num));
num = "";
while ( !isParenthesesLeft(symbolStack.peek()) ){
int num1 = numStack.pop();
int num2 = numStack.pop();
int popSymbol = symbolStack.pop();
int calculate = calculate(num1, num2, popSymbol);
numStack.push(calculate);
}
symbolStack.pop();
}
if( i == waitCal.length()-1 && isNum(c)){
numStack.push(Integer.parseInt(num));
num = "";
}
}
while (!symbolStack.isEmpty()){
int num1 = numStack.pop();
int num2 = numStack.pop();
int popSymbol = symbolStack.pop();
int calculate = calculate(num1, num2, popSymbol);
numStack.push(calculate);
}
return numStack.pop();
}
private static void symbolPush(char c, ArrayStack<Integer> numStack, ArrayStack<Character> symbolStack) {
if (symbolStack.isEmpty()) {
symbolStack.push(c);
return ;
}
int topVal = symbolStack.peek();
int priorityPeek = getPriority((char) topVal);
int priorityC = getPriority(c);
if (priorityC >= priorityPeek){
symbolStack.push(c);
}else {
int num1 = numStack.pop();
int num2 = numStack.pop();
int symbolTop = symbolStack.pop();
int result = calculate(num1,num2,symbolTop);
numStack.push(result);
symbolPush(c,numStack,symbolStack);
}
}
private static int calculate(int num1, int num2, int symbolTop) {
char symbol = (char)symbolTop;
return switch (symbol) {
case '+' -> num2 + num1;
case '-' -> num2 - num1;
case '*' -> num2 * num1;
case '/' -> num2 / num1;
default -> throw new RuntimeException("error symbol");
};
}
private static int getPriority(char topVal) {
return switch (topVal) {
case '+', '-' -> 0;
case '*', '/' -> 1;
default -> -1;
};
}
private static boolean isSymbol(char c) {
return switch (c) {
case '+', '-', '*', '/' -> true;
default -> false;
};
}
private static boolean isNum(char c) {
return c >= '0' && c <= '9';
}
private static boolean isParenthesesLeft(char c) {
return c == '(';
}
private static boolean isParenthesesRight(char c) {
return c == ')';
}
}
测试:
package com.example.stack.basic;
import com.example.stack.improve.ImproveCalculate;
public class Test {
public static void main(String[] args) {
String waitCal = "3+2*2+13";
int result = Calculate.calculate(waitCal);
System.out.printf("%s=%d\n",waitCal,result);
String waitCal2 = "3+2*(2+5*5)*2+13";
int result2 = ImproveCalculate.calculate(waitCal2);
System.out.printf("%s=%d\n",waitCal2,result2);
}
}
3+2*2+13=20
3+2*(2+5*5)*2+13=124
|