java 实现栈模型(附源码)
1.栈
1.1栈的解释
主要特点:先进后出
栈是限制插入和删除只能在一个位置上进行的线性表。其中,允许插入和删除的一端位于表的末端,叫做栈顶(top),不允许插入和删除的另一端叫做栈底(bottom)。对栈的基本操作有 PUSH(压栈)和 POP(出栈),前者相当于表的插入操作(向栈顶插入一个元素),后者则是删除操作(删除一个栈顶元素)。栈是一种**后进先出(LIFO)**的数据结构,最先被删除的是最近压栈的元素。
栈模型
压栈:
弹栈:
栈实现
由于栈是一个表,因此任何实现表的方法都可以用来实现栈。主要有两种方式,链表实现和数组实现。
-
链表实现栈
可以使用单链表来实现栈。通过在表顶端插入一个元素来实现 PUSH,通过删除表顶端元素来实现 POP。使用链表方式实现的栈又叫动态栈。动态栈有链表的部分特性,即元素与元素之间在物理存储上可以不连续,但是功能有些受限制,动态栈只能在栈顶处进行插入和删除操作,不能在栈尾或栈中间进行插入和删除操作
-
数组实现栈
栈也可以用数组来实现。使用数组方式实现的栈叫静态栈。
1.2栈的应用场景
- 子程序的调用:在跳往子程序前,会先将下个指令的地址存到堆栈中,直到子程序执行完后再将地址取出,以回到原来的程序中。
- 处理递归调用:和子程序的调用类似,只是除了储存下一个指令的地址外,也将参数、区域变量等数据存入堆栈中。
- 表达式的转换[中缀表达式转后缀表达式]与求值(实际解决)。
- 二叉树的遍历。
- 图形的深度优先(depth一first)搜索法。
1.3栈的实现
package shujujiegou.stack;
import java.util.Arrays;
public class ArrayStack {
/**
* 栈的大小
*/
private int maxStack;
/**
* 数组用来模拟栈
*/
private int[] stack;
/**
* 表示栈顶所在的位置,默认情况下如果没有数据时,使用-1
*/
private int top = -1;
public ArrayStack(int maxStack) {
this.maxStack = maxStack;
stack=new int[maxStack];
}
/**
* 1.压栈
* 2.弹栈
* 3.判断是否是空栈
* 4.当前栈中是否是满栈
*/
/**
* 判断是否已经满栈
*/
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("栈已满!");
}
top++;//指针到下一个位置
stack[top]=val;//添加元素
}
/*
* 弹栈
*/
public int pop(){
//在弹栈之前要先判断是否为空栈
if (isEmpty()){
throw new RuntimeException("此栈为空!");
}
int value= stack[top];
top--;
return value;
}
/**
* 查看栈中所有元素
*/
public void list(){
System.out.println(Arrays.toString(stack));
}
}
1.4栈的使用例子
1.4.1判断回文数
回文: 一个单词、短语或数字,从前往后写和从后往前写都是一样的。比如,单词“dad”、“racecar”就是回文;如果忽略空格和 标点符号,下面这个句子也是回文,“A man, a plan, a canal: Panama”, 数字1001 也是回文。
思路:
- 将拿到的字符串的每个字符按从左至右的顺序压入栈。
- 当字符串中的字符都入栈后,栈内就保存了一个反转后的字符串,最后的字符在栈顶,第一个字符在栈底。
- 进行弹栈操作,最后比较出栈与入栈的数据是否相等,如果相等,则是回文,如果不相等则不是回文。
代码实现
package shujujiegou.stack;
/**
* 回文数据
* 回文: aba racecar
* 需求:通过上面以数组模拟栈来判断一个字符串是否是一个回文数据
*/
public class TestApp {
public static void main(String[] args) {
System.out.println(detecation("11"));
}
public static boolean detecation(String val){
if (val.length()==0){
throw new RuntimeException("为空数据!无法进行操作!");
}
//获取数据长度
int length=val.length();
/**
* 初始化栈对象
*/
ArrayStack arrayStack = new ArrayStack(length);
/**
* 压栈
*/
for (int i = 0; i < length; i++) {
//这里我们要注意不能使用var.length来作为判断的长度
//因为这里的长度是逐渐变化的
arrayStack.push(val.charAt(i));
}
//设置新的字符串来接收弹栈后的数据
String newval="";
for (int i = 0; i <length ; i++) {
char pop = (char)arrayStack.pop();
newval+=pop;
}
if (newval.equals(val)){
return true;
}
return false;
}
}
1.4.2加减乘除栈实现
栈模型
package shujujiegou.stack;
import java.util.Arrays;
public class ArrayStack {
/**
* 栈的大小
*/
private int maxStack;
/**
* 数组用来模拟栈
*/
private int[] stack;
/**
* 表示栈顶所在的位置,默认情况下如果没有数据时,使用-1
*/
private int top = -1;
public ArrayStack(int maxStack) {
this.maxStack = maxStack;
stack=new int[maxStack];
}
/**
* 1.压栈
* 2.弹栈
* 3.判断是否是空栈
* 4.当前栈中是否是满栈
*/
/**
* 判断是否已经满栈
*/
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("栈已满!");
}
top++;//指针到下一个位置
stack[top]=val;//添加元素
}
/**
* 弹栈
* @return
*/
public int pop(){
//在弹栈之前要先判断是否为空栈
if (isEmpty()){
throw new RuntimeException("此栈为空!");
}
int value= stack[top];
top--;
return value;
}
/**
* 查看栈中所有元素
*/
public void list(){
System.out.println(Arrays.toString(stack));
}
/**
* 栈中元素存在的个数
* @return
*/
public int length(){
return this.top+1;
}
/**
* 判断是否是一个运算符 + - * /
*
*/
public boolean isOper(char v){
return v=='+'||v=='-'||v=='*'||v=='/';
}
/**
* 判断运算符优先级 使用数字表示优先级大小,数字越大的优先级越大
*/
public int priority(int oper){
if (oper=='*'||oper=='/'){
return 1;
}else if (oper=='+'||oper=='-'){
return 0;
}else {
return -1;
}
}
/**
* 获取栈顶数据
* @return
*/
public int peek(){
return this.stack[top];
}
/**
* 获取栈的容量
*/
public int stackLength(){
return this.stack.length;
}
/**
* 计算两个数进行运算后的结果
* 2-3
* 3:num1,2:num2
*/
public int calculate(int num1,int num2,int oper){
//计算结果
int result = 0;
switch (oper){
case '+':
result = num1+num2;
break;
case '-':
result = num2-num1;
break;
case '*':
result = num1*num2;
break;
case '/':
result = num2/num1;
break;
default:
break;
}
return result;
}
}
实现计算加减乘除栈
package shujujiegou.stack;
import java.util.Arrays;
public class TestOperation {
public static void main(String[] args) {
System.out.println(operations("44+32*24/1"));
}
public static int operations(String str){
/**
* 1.需要遍历字符串,获取每一个字符
* 2.判断当前字符是一个运算符还是一个数字
* 3.把数字存放在数字栈中,把运算符放在运算符栈
* 4.运算符栈: 如果是一个空栈,那么直接运算符入栈,如果运算符栈中已经了其他运算符
* 就需要先对比运算符优先级,新进来的运算符如果小于等于原栈中运算符,那么需要把原运算符弹栈
* ,数字栈中数字进行弹栈,进行运算,运算后的结果重新放入数字栈中,新运算符入栈。
* 如果新运算符优先级大于原符号栈中运算符,那么新的符号直接入栈
*/
int length=str.length();
//设置符号栈和数字栈
ArrayStack numstack = new ArrayStack(length);
ArrayStack symbolstack = new ArrayStack(length);
//设置默认值
int temp1 = 0;
int temp2 = 0;
int symbolChar = 0;
int result = 0;
String values = "";
for (int i = 0; i <length ; i++) {
//取值
char c=str.charAt(i);
//判断是否为符号
if (symbolstack.isOper(c)){
//判断是否为空栈
if (!symbolstack.isEmpty()){
//判断符号优先级
//判断栈顶元素与获得到的元素进行优先级比较
//这里是处理优先级高的符号
if (symbolstack.priority(c)<=symbolstack.priority(symbolstack.peek())){
/**
* 1.去符号栈中获取栈顶的符号
* 2.去数字栈中获取两个数字
*/
temp1=numstack.pop();
temp2=numstack.pop();
symbolChar=symbolstack.pop();
//计算结果
result=numstack.calculate(temp1,temp2,symbolChar);
//这里我们要注意的是:在数字栈弹栈完成以后:我们需要将结果重新压栈。这样压栈到最后栈顶元素就是我们最后的计算结果
//把计算结果放入栈中
numstack.push(result);
//把当前符号压入符号栈
symbolstack.push(c);
}else {
//这里处理优先级相同或者相等的运算符
symbolstack.push(c);
}
}else {
//如果是空符号栈,讲运算符直接压栈
symbolstack.push(c);
}
}
//这里判断数字位
else {
values+=c;//先将字符串赋值
if (i==length-1){
//如果为数字栈栈顶元素直接压栈。
numstack.push(Integer.parseInt(values));
}else {
//获取第二位数字元素
char data = str.substring(i+1,i+2).charAt(0);
if (symbolstack.isOper(data)){
numstack.push(Integer.parseInt(values));
values="";
}
}
}
}
//计算总和
while (true){
if (symbolstack.isEmpty()){
break;
}
temp1 = numstack.pop();
temp2 = numstack.pop();
symbolChar = symbolstack.pop();
result = numstack.calculate(temp1,temp2,symbolChar);
numstack.push(result);
}
int results=numstack.pop();
return results;
}
}