1.栈的介绍
栈是限制插入和删除只能在一个位置上进行的线性表。其中,允许插入和删除的一端位于表的末端,叫做栈顶(top),不允许插入和删除的另一端叫做栈底(bottom)。对栈的基本操作有 PUSH(压栈)和 POP (出栈),前者相当于表的插入操作(向栈顶插入一个元素),后者则是删除操作(删除一个栈顶元素)。栈是一种后进先出(LIFO)的数据结构,最先被删除的是最近压栈的元素。
弹栈:
栈实现
由于栈是一个表,因此任何实现表的方法都可以用来实现栈。主要有两种方式,链表实现和数组实现。
链表实现栈
可以使用单链表来实现栈。通过在表顶端插入一个元素来实现 PUSH,通过删除表顶端元素来实现 POP。使用链表方式实现的栈又叫动态栈。动态栈有链表的部分特性,即元素与元素之间在物理存储上可以不连续,但是功能有些受限制,动态栈只能在栈顶处进行插入和删除操作,不能在栈尾或栈中间进行插入和删除操作。
数组实现栈
栈也可以用数组来实现。使用数组方式实现的栈叫静态栈。
2.栈的应用场景
3.栈的快速入门
习题1:使用数组来模拟栈的使用
ArrayStack类
package stack;
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];
}
//判断栈是否是空栈
public boolean isFull(){
return this.top==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(){
//是否是空栈
if (isEmpty()){
throw new RuntimeException("空栈,未找到数据!");
}
for (int i=0;i<stack.length;i++){
System.out.printf("stack[%d]=%d\n", i ,stack[i]);
}
}
//栈中元素存在的个数
public int length(){
return this.top+1;
}
}
习题2:回文数
回文: 一个单词、短语或数字,从前往后写和从后往前写都是一样的。比如,单词“dad”、“racecar”就是回文;如果忽略空格和 标点符号,下面这个句子也是回文,“A man, a plan, a canal: Panama”, 数字1001 也是回文。
思路:使用栈,可以轻松判断一个字符串是否是回文。我们将拿到的字符串的每个字符按从左至右的顺序压入栈。当字符串中的字符都入栈后,栈内就保存了一个反转后的字符串,最后的字符在栈顶,第一个字符在栈底。
Test类
package stack;
import java.util.Arrays;
public class Test {
public static void main(String[] args) {
/**
* 回文数据
* 回文:aba racecar 回文就是压栈字符串顺序和出栈字符串顺序相等。
* 需求:通过上面数组模拟栈,判断字符串是否是一个回文数据
*/
System.out.println(detecation("aba"));
}
public static boolean detecation(String val){
//初始化栈对象
ArrayStack arrayStack=new ArrayStack(10);
//获取字符串长度
int length = val.length();
//把字符串数据逐次获取字符压栈到数组中
for (int i=0;i<length;i++){
arrayStack.push(val.charAt(i));
}
//把字符串的数据逐次弹出
String newVal="";
int length1=arrayStack.length();
for (int i=0;i<length1;i++){
//是否是一个空栈
if (!arrayStack.isEmpty()){
char pop= (char) arrayStack.pop();
newVal+=pop;
}
}
if (val.equals(newVal)){
return true;
}
return false;
}
}
测试结果
4.栈实现计算器
首先在ArrayStack类中编写测试类所需要的方法
ArrayStack类
package stack;
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];
}
//判断栈是否是空栈
public boolean isFull(){
return this.top==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(){
//是否是空栈
if (isEmpty()){
throw new RuntimeException("空栈,未找到数据!");
}
for (int i=0;i<stack.length;i++){
System.out.printf("stack[%d]=%d\n", i ,stack[i]);
}
}
//栈中元素存在的个数
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;
}
}
//获取栈的栈顶数据
public int peek(){
return this.stack[top];
}
//获取栈的容量
public int stackLength(){
return this.stack.length;
}
//计算两个数进行运算后的结果(出栈时是先进后出)
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;
}
}
Test2测试类
package stack;
public class Test2 {
public static void main(String[] args) {
String str="4+3*2-1";
ArrayStack numStack=new ArrayStack(10);
ArrayStack symbolStack=new ArrayStack(10);
int temp1=0;
int temp2=0;
int symbolChar=0;
int result=0;
//获取字符串的长度
int length = str.length();
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 c1 = str.substring(i + 1, i + 2).charAt(0);
if (symbolStack.isOper(c1)){
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 res=numStack.pop();
System.out.println("结果是:"+res);
}
}
测试结果