- 子程序的调用:在跳往子程序前,会先将下个指令的地址存到堆栈中,直到子程序执行完后在将地址去除,以回到原来的程序中
- 处理递归调用: 和子程序的调用类似,只是出了存储下一个指令的地址外,也将参数,区域变量的数据存入堆栈中
- 表达式的转换[ 中缀表达式转后缀表达式 ] 与求值(实际解决)
- 二叉树的遍历
- 图形的深度优化(depth - first)
数组模拟栈
package com.example.dataSructure.stack;
import java.util.Scanner;
/**
* 数组模拟栈
* @author qubing
* @date 2022/2/18 10:24
*/
public class ArrayStackDome {
public static void main(String[] args) {
ArrayStack stack = new ArrayStack(4);
String key = "";
//是否退出菜单
boolean loop = true;
Scanner scanner = new Scanner(System.in);
while (loop){
System.out.println("show : 表示显示栈");
System.out.println("exit : 退出程序");
System.out.println("push : 添加数据到栈(入栈)");
System.out.println("pop : 从栈取出数据(出栈)");
System.out.println("请输入你的选择");
key = scanner.next();
switch (key){
case "show":
stack.show();
break;
case "push":
System.out.println("请输入数值");
int i = scanner.nextInt();
stack.push(i);
break;
case "pop":
try {
int res = stack.pop();
System.out.println("出栈的数据: "+ res);
}catch (Exception e){
System.out.println(e.getMessage());
}
break;
case "exit":
scanner.close();
loop = false;
break;
default:
break;
}
}
System.out.println("程序退出");
}
}
class ArrayStack{
/**
* 栈的大小
*/
private int maxSize;
/**
* 数组模拟栈
*/
private int[] stack;
/**
* 栈顶,初始化为-1,表示没有数据
*/
private int top = -1;
public ArrayStack(int maxSize){
this.maxSize = maxSize;
stack = new int[this.maxSize];
}
/**
* 是否满了
* @return boolean
*/
public boolean isFull(){
return top == maxSize-1;
}
/**
* 是否栈空
* @return boolean
*/
public boolean isEmpty(){
return top == -1;
}
/**
* 入栈
* @param value 需要放入的数据
*/
public void push(int value){
if(isFull()){
System.out.println("栈满");
return;
}
top++;
stack[top] = value;
}
/**
* 出栈 将栈顶的数据返回
* @return int 返回的数据
*/
public int pop(){
if(isEmpty()){
throw new RuntimeException("栈空");
}
int val = stack[top];
top--;
return val;
}
/**
* 显示栈
*/
public void show(){
if(isEmpty()){
System.out.println("栈空,没有数据");
return;
}
for (int i = top; i >= 0 ; i--) {
System.out.printf("stack[ %d ] = %d\n",i,stack[i]);
}
}
}
计算表达式小功能
package com.example.dataSructure.stack;
/**
* 一位数的加减乘除
* @author qubing
* @date 2022/2/18 11:09
*/
public class Calculator {
public static void main(String[] args) {
String expression = "30*2+6-2";
ArrayStack2 numStack = new ArrayStack2(10);
ArrayStack2 operStack = new ArrayStack2(10);
int index = 0;
int num1 ;
int num2 ;
int oper ;
int res ;
char ch ;
//用于拼接多位数
String keepNumber = "";
while (true){
ch = expression.substring(index,index+1).charAt(0);
if(operStack.isOper(ch)){
//为空入栈
if(operStack.isEmpty()){
operStack.push(ch);
}
else{
//如果操作栈有操作符,判断优先级
if(operStack.priority(ch) <= operStack.priority(operStack.peek())){
num1 = numStack.pop();
num2 = numStack.pop();
oper = operStack.pop();
if(num1 <= num2){
res = numStack.cal(num1,num2,oper);
}else{
res = numStack.cal(num2,num1,oper);
}
//将算出的数值放入数字栈
numStack.push(res);
//当前操作符放入符号栈
operStack.push(ch);
}
else{
//当前操作符优先级>栈中的优先级
operStack.push(ch);
}
}
}
else{
//如果是数,直接入数栈 注意: 此时的ch是 char类型的(‘ ’)并不是数值,ch - 48 才是int的10进制数
/*numStack.push(ch - 48); //这是单位数计算没问题,多位数就有问题*/
//处理多位数,不能直接入栈,因为有可能是多位数,处理数时需要向expression的表达式后面再看一位,
// 是运算符便再入栈
keepNumber += ch;
if(index == expression.length()-1){
numStack.push(Integer.parseInt(keepNumber));
}
else{
//判断下一位是不是数字,如果是就继续扫描,如果是运算符便入栈
if(operStack.isOper(expression.substring(index+1,index+2).charAt(0))){
numStack.push(Integer.parseInt(keepNumber));
keepNumber = "";
}
}
}
index++;
//是否扫描到 expression 的最后了
if(index >= expression.length()){
break;
}
}
//表达式执行完后,顺序的从数栈和符号栈中pop出相应的数和符号,并运行
while (true){
// 符号栈为空说明运行到了最后,字符栈的最后一个数便是结果
if (operStack.isEmpty()){
break;
}else{
num1 = numStack.pop();
num2 = numStack.pop();
oper = operStack.pop();
if(num1 <= num2){
res = numStack.cal(num1,num2,oper);
}else{
res = numStack.cal(num2,num1,oper);
}
numStack.push(res);
}
}
System.out.printf("表达式 %s = %d",expression,numStack.pop());
}
}
class ArrayStack2{
/**
* 栈的大小
*/
private int maxSize;
/**
* 数组模拟栈
*/
private int[] stack;
/**
* 栈顶,初始化为-1,表示没有数据
*/
private int top = -1;
public ArrayStack2(int maxSize){
this.maxSize = maxSize;
stack = new int[this.maxSize];
}
/**
* 是否满了
* @return boolean
*/
public boolean isFull(){
return top == maxSize-1;
}
/**
* 是否栈空
* @return boolean
*/
public boolean isEmpty(){
return top == -1;
}
/**
* 入栈
* @param value 需要放入的数据
*/
public void push(int value){
if(isFull()){
System.out.println("栈满");
return;
}
top++;
stack[top] = value;
}
/**
* 出栈 将栈顶的数据返回
* @return int 返回的数据
*/
public int pop(){
if(isEmpty()){
throw new RuntimeException("栈空");
}
int val = stack[top];
top--;
return val;
}
/**
* 显示栈
*/
public void show(){
if(isEmpty()){
System.out.println("栈空,没有数据");
return;
}
for (int i = top; i >= 0 ; i--) {
System.out.printf("stack[ %d ] = %d\n",i,stack[i]);
}
}
/**
* 返回运算符的优先级
* 表达式 只有加减乘除的时候
*/
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 =='*';
}
/**
* 计算方法
*/
public int cal(int num1,int num2,int oper){
int res = 0;
switch (oper){
case '+':
res = num1 + num2;
break;
case '-':
res = num2 - num1;
break;
case '*':
res = num1 * num2;
break;
case '/':
res = num2/num1;
break;
default:
break;
}
return res;
}
/**
* 查看当前栈顶的值,不是真正的出栈
*/
public int peek(){
return stack[top];
}
}
前缀、中缀、后缀表达式(逆波兰表达式)
前缀表达式的计算机求值
从左至右扫描表达式,遇到数字时,将数字压入堆栈,遇到运算符是,弹出栈顶的两个数,用运算符对它们做相应的计算(栈顶元素和次顶元素),并且结果入栈;重复上述过程。
1.中缀表达式
(3+4)X5-6
2.前缀表达式
-x+3456
3.后缀表达式(逆波兰表达式)
- 后缀表达式又称逆波兰表达式 与前缀表达式相似,只是运算符位于操作数之后
- 比如: (3+4)x5-6 对应的后缀表的是为 3 4 + 5 x 6 -
正常表达式 | 逆波兰表达式 |
---|---|
a+b | a b + |
a + (b - c) | a b c - |
a+(b - c)*d | a b c - d * + |
a+d*(b - c) | a d b c - * + |
a = 1 + 3 | a 1 3 + = |
实例
package com.example.dataSructure.stack;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
/**
* 逆波兰计算器
* @author qubing
* @date 2022/2/18 13:55
*/
public class PolandNotation {
public static void main(String[] args) {
//逆波兰表达式
//(3+4)x5-6 -> 3 4 + 5 x 6 -
//(30+4)x5-6 -> "30 4 + 5 * 6 -" == 164;
//4*5-8+60+8/2 -> 4 5 * 8 - 60 + 8 2 / + == 76
//为了方便用空格隔开
String suffixExpression = "4 5 * 8 - 60 + 8 2 / +";
List<String> listString = getListString(suffixExpression);
int calculate = calculate(listString);
System.out.println(calculate);
}
/**
* 处理后缀表达式
* @param suffixExpression 表达式
* @return List<String>
*/
public static List<String> getListString(String suffixExpression){
String[] split = suffixExpression.split(" ");
List<String> list = new ArrayList<>();
for (String ele : split){
list.add(ele);
}
return list;
}
/**
* 计算
* @param ls 集合
* @return int
*/
public static int calculate(List<String> ls){
//只需要一个栈即可
Stack<String> stack = new Stack<>();
for (String item : ls) {
//使用正则表达式取出数
if(item.matches("\\d+")){
//匹配的是多位数
stack.push(item);
}
else{
//如果是运算符 在栈里面取出两个数
int num2 = Integer.parseInt(stack.pop());
int num1 = Integer.parseInt(stack.pop());
int res = 0;
if(item.equals("+")){
res = num1 + num2;
}
else if(item.equals("-")){
res = num1 - num2;
}
else if(item.equals("*")){
res = num1 * num2;
}
else if(item.equals("/")){
res = num1 / num2;
}else{
throw new RuntimeException("运算符有误");
}
stack.push(String.valueOf(res));
}
}
return Integer.parseInt(stack.pop());
}
}
中缀表达式转后缀表达式