栈
栈的介绍
- 栈是限制插入和删除只能在一个位置上进行的线性表。其中,允许插入和删除的一端位于表的末端,叫做栈顶(top),不允许插入和删除的一端叫做栈底(bottom)。对栈的基本操作有push(压栈)和pop(弹栈/出栈),前者向栈顶插入一个元素,后者是删除一个栈顶元素。栈是一种后进先出(LIFO)的数据结构,最先被删除的是最近压栈的元素。
栈实现
- 由于栈是一个表,因此任何实现表的方法都可以用来实现栈,主要有两种方式,链表实现和数组实现。
链表实现栈-动态栈
- 可以使用单链表来实现栈。通过在表顶端插入一个元素来实现push,通过删除顶端元素实现pop。
- 动态栈有链表的部分特性,即元素与元素在物理存储上可以不连续,但是功能受限制,动态栈只能在栈顶进行插入和删除操作,不能在栈底或栈中间进行插入和删除操作。
数组实现栈-静态栈
栈的应用场景
- 1、子程序的调用:在跳往子程序前,会先将下个指定的地址存到堆栈中,直到子程序执行完后再将地址取出,以回到原来的程序中;
- 2、处理递归调用:和子程序的调用类似,只是除了存储下一个指令的地址外,也将参数、区域变量等数据存入堆栈中;
- 3、表达式的转换(中缀表达式转后缀表达式)与求值;
- 4、二叉树的遍历;
- 5、图的深度优先搜索法。
静态栈数据结构
package com.acti.stack;
/**
* author hongyeci
* date 20220715
* version 1.0
* remark 数组实现栈-静态栈 数据结构
*/
public class ArrayStack {
//栈大小
private int maxStack;
//数组模拟栈
private Object[] stack;
//栈顶位置-默认为空栈
private int top = -1;
public ArrayStack(int maxStack) {
this.maxStack = maxStack;
stack = new Object[maxStack];
}
/**
* 判断是否空栈
* @return boolean
*/
public boolean isEmpty(){
return this.top == -1;
}
/**
* 判断是否满栈
* @return boolean
*/
public boolean isFull(){
return this.top == this.maxStack-1;
}
/**
* 栈中元素个数
* @return 元素个数
*/
public int length(){
return this.top+1;
}
/**
* 压栈、入栈
* @param val 入栈元素
*/
public void push(Object val){
if (isFull()){
throw new RuntimeException("此栈已满...");
}
top++;
stack[top] = val;
}
/**
* 弹栈、出栈
* @return 出栈元素
*/
public Object pop(){
if (isEmpty()){
throw new RuntimeException("空栈,未找到数据...");
}
Object value = stack[top];
top--;
return value;
}
/**
* 查看栈中的所有元素
*/
public void stackList(){
if (isEmpty()){
throw new RuntimeException("空栈,栈中没有数据...");
}
for (int i=0;i<stack.length;i++){
System.out.printf("stack[%d]=%c\n",i,stack[i]);
}
}
/**
* 获取栈顶元素
* @return 返回栈顶元素
*/
public Object stackTop(){
return this.stack[top];
}
}
实例
回文字符串
/**
* 判断是否是回文字符串
* @param val 字符串
* @return boolean
*/
public static boolean isPalindromes(String val){
ArrayStack arrayStack = new ArrayStack(val.length());
//入栈
for (int i=0;i<val.length();i++){
arrayStack.push(val.charAt(i));
}
//出栈
String newVal = "";
int len = arrayStack.length();
for (int j=0;j<len;j++){
newVal += arrayStack.pop();
}
return val.equals(newVal);
}
实现简单计算
package com.acti.stack;
/**
* author hongyeci
* date 20220716
* version 1.0
* remark 简单计算类 + - * /
*/
public class Calculation {
/**
* 计算符号
*/
private final static char PLUS='+';
private final static char SUBTRACT='-';
private final static char MULTIPLY='*';
private final static char DIVIDE='/';
/**
* 判断是否是运算符
* @param v
* @return
*/
public static boolean isOper(char v){
return PLUS==v || SUBTRACT==v || MULTIPLY==v || DIVIDE==v;
}
/**
* 运算符优先级
* @param v 运算符字符
* @return
*/
public static int priority(char v){
if (MULTIPLY==v || DIVIDE==v){
return 1;
}else if (PLUS==v || SUBTRACT==v){
return 0;
}else {
return -1;
}
}
/**
* 两数计算
* @param num1 数字1
* @param num2 数字2
* @param v 运算符
* @return 计算结果
*/
public static int calculate(int num1,int num2,char v){
int result = 0;
switch (v){
case PLUS:
result = num2+num1;
break;
case SUBTRACT:
result = num2-num1;
break;
case MULTIPLY:
result = num2*num1;
break;
case DIVIDE:
result = num2/num1;
break;
default:
break;
}
return result;
}
}
/**
* 静态栈--简单计算
* @param oper 计算字符串 "33+22-1*5"
* @return 计算结果
*/
public static int calculateOper(String oper){
//初始化数字栈和符号栈
ArrayStack numStack = new ArrayStack(oper.length());
ArrayStack symbolStack = new ArrayStack(oper.length());
int result = 0;
char symbol = '0';
int num1 = 0;
int num2 = 0;
String str = "";
for (int i=0;i<oper.length();i++){
//获取每个字符
char v = oper.charAt(i);
//判断是否是运算符--是 则入符号栈
if (Calculation.isOper(v)){
numStack.push(str);
str = "";
//判断符号栈是否为空
if(!symbolStack.isEmpty()){
//否 判断运算符优先级
if (Calculation.priority(v)<=Calculation.priority((Character) symbolStack.stackTop())){
//入栈运算符优先级小于等于符号栈中运算符优先级时,先对符号栈中栈顶符号元素及数字栈中两个数字元素进行运算
symbol = (char) symbolStack.pop();
num1=Integer.parseInt(numStack.pop().toString());
num2=Integer.parseInt(numStack.pop().toString());
result = Calculation.calculate(num1,num2,symbol);
//计算结果入数字栈
numStack.push(result);
}
}
//入栈运算符优先级大于符号栈顶运算符优先级时,直接入栈
//符号栈为空时,直接入栈
symbolStack.push(v);
}else {
str += v;
//如果是最后一个数字字符
if(i==oper.length()-1){
numStack.push(str);
while (true){
if (symbolStack.isEmpty()){
break;
}
num1=Integer.parseInt(numStack.pop().toString());
num2=Integer.parseInt(numStack.pop().toString());
symbol= (char) symbolStack.pop();
result=Calculation.calculate(num1,num2,symbol);
numStack.push(result);
}
}
}
}
return Integer.parseInt(numStack.stackTop().toString());
}
数据结构相关代码仓库地址:
https://gitee.com/red_leafzsp/structureAlgorithms
浙公网安备 33010602011771号