目录
1. 概念
2. 栈的使用
2.1 方法
2.2 示例
3. 栈的模拟实现
4. 栈的应用场景
4.1 题目1:不可能的出栈序列
4.2 题目2:逆序打印单链表
4.3 题目3:逆波兰表达式求值
4.4 题目4:括号匹配
4.5 题目5:栈的压入、弹出训练
4.6 题目6:最小栈
(1)栈是一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。
(2)进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。
(3)栈中的数据元素遵循后进先出的原则;
(4)压栈:栈的插入操作叫做进栈或压栈或入栈,入数据在栈顶;
出栈:栈的删除操作叫做出栈,出数据在栈顶;
方法 | 功能 |
Stack() | 构造一个空栈 |
E push(E e) | 将e入栈并返回e |
E pop() | 将栈顶元素出栈并返回 |
E peek() | 获取栈顶元素 |
int size() | 获取栈中有效元素个数 |
boolean empty() | 检测栈是否为空 |
public static void main(String[] args) {
Stack stack = new Stack<>();
for(int i=0;i<=5;i++){
stack.push(i); // 压栈
}
// 获取栈顶元素
System.out.println(stack.peek());
Integer a = stack.pop(); // 出栈栈顶元素
System.out.println(a);
System.out.println(stack.peek());
System.out.println(stack.size());
}
Stack继承于Vector,查Vector源码可知vector内部用数组实现,故而模拟实现采用数组栈;
(1)包类关系:
(2)MyStack:
package TestMyStack;
import java.util.Arrays;
public class MyStack {
public int[] elem;
public int useSize;
public MyStack(){
this.elem = new int[10];
}
// 压栈
public void push(int val){
if(isFull()){
// 扩容
reSize();
}
elem[useSize] = val;
this.useSize++;
}
// 判满
public boolean isFull(){
if(elem.length == this.useSize){
return true;
}
return false;
}
// 扩容
public void reSize(){
elem = Arrays.copyOf(elem, 2*elem.length);
}
// 出栈并返回出栈元素
public int pop(){
if(isEmpty()){
throw new EmptyException();
}
// int val = elem[this.useSize-1];
// this.useSize--;
// return val;
return this.elem[--this.useSize];
}
// 判空
public boolean isEmpty(){
return this.useSize==0;
}
// 获取栈顶元素
public int peek(){
return this.elem[this.useSize-1];
}
}
(3)EmptyException:
package TestMyStack;
public class EmptyException extends RuntimeException{
public EmptyException(){
}
}
若进栈序列为1,2,3,4,进栈过程中可以出栈,则不可能的出栈序列是:C
A. 1,4,3,2 B. 2,3,4,1 C.3,1,4,2 D.3,4,2,1
(1)单链表的递归逆序打印法:
public void fun1(ListNode pHead){
// 递归逆序打印单链表
if(pHead == null){
return;
}
if(pHead.next == null){
System.out.println(pHead.val);
}
fun1(pHead.next);
System.out.println(pHead.val);
}
(2)单链表的循环递归逆序打印法:
public void fun2(ListNode pHead){
Stack stack = new Stack<>();
ListNode cur = head;
while(cur!=null){
stack.push(cur);
cur = cur.next;
}
// 遍历栈
while(!stack.isEmpty()){
ListNode top = stack.pop();
System.out.print(top.val+" ");
}
System.out.println();
}
题目链接:150. 逆波兰表达式求值 - 力扣(LeetCode)
解题思路:遍历后缀算数表达式数组,若为数据则入栈,若为算术运算符则出栈栈顶两元素分别作为后操作数和前操作数,再将计算结果入栈,继续向后遍历数组,循环操作,直至栈中仅有一个元素,就是最终值;
代码:
class Solution {
public int evalRPN(String[] tokens) {
Stack stack = new Stack<>();
for(String x: tokens){
if(!isOperation(x)){
stack.push(Integer.parseInt(x));
}else{
int num2 = stack.pop();
int num1 = stack.pop();
switch(x){
case "+":
stack.push(num1+num2);
break;
case "-":
stack.push(num1-num2);
break;
case "*":
stack.push(num1*num2);
break;
case "/":
stack.push(num1/num2);
break;
}
}
}
return stack.pop();
}
private boolean isOperation(String x){
if(x.equals("+")||x.equals("-")||x.equals("*")||x.equals("/")){
return true;
}
return false;
}
}
题目链接:20. 有效的括号 - 力扣(LeetCode)
代码:
class Solution {
public boolean isValid(String s) {
Stack stack = new Stack();
for(int i=0;i
题目链接:栈的压入、弹出序列_牛客题霸_牛客网
解题思路:定义i下标遍历pushV,j下标遍历popV,将pushV的元素入栈,当二者元素不相等时,继续入栈pushV元素;当二者元素相等时,出栈栈顶元素,i和j均++;
代码:
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param pushV int整型一维数组
* @param popV int整型一维数组
* @return bool布尔型
*/
public boolean IsPopOrder (int[] pushV, int[] popV) {
Stack stack = new Stack<>();
int j=0;
for(int i=0;i
题目链接:155. 最小栈 - 力扣(LeetCode)
解题思路:为目标栈开辟一个储存最小值的栈,依次遍历目标栈,将最小的元素入栈最小栈,最小栈栈顶元素就是目标栈的最小元素,且能在常数时间内检索到最小元素;
代码:
class MinStack {
private Stack stack;
private Stack minStack;
public MinStack() {
stack = new Stack<>();
minStack = new Stack<>();
}
public void push(int val) {
stack.push(val);
if(minStack.empty()){
minStack.push(val);
}else{ //minStack不为空
if(val <= minStack.peek()){
// 如果要插入的值比minStack的栈顶元素小
minStack.push(val);
// 注意当val==minStack栈顶元素时,也需要将该元素入栈minStack
// 因为stack出栈元素时,如果该元素是minStack中的元素,该元素也需要出栈
// 以保证在出栈stack最小元素时,minStack中的最小元素不受影响
}
}
}
public void pop() {
if(!stack.empty()){
Integer val = stack.pop();
if(val.equals(minStack.peek())){
minStack.pop();
}
// 如果对元素拆箱为int类型,就可使用==进行判等
}
}
public int top() {
if(!stack.empty()){
return stack.peek();
}
return -1;
}
public int getMin() {
return minStack.peek();
}
}