Stack
栈的概念和使用
栈的概念
栈(Stack):一种特殊的线性表,只允许再栈的一端进行插入和删除元素 ,这一端点被称为栈顶 ,另一端就是栈顶
栈中有两种使用:
入栈(push):插入数据进入栈中,入栈在栈顶
出栈(pop):删除栈中数据,出的是栈顶的数据
遵循的是先入后出的原则

栈的使用
方法 | 功能 |
---|---|
Stack() | 构造空的栈 |
E push(E e) | 将e入栈,返回e |
E pop() | 将栈顶元素取出 |
E peek() | 获取栈顶元素 |
int size() | 栈的有效元素个数 |
boolean empty() | 判断栈是否为空 |
E push(E e) 将e入栈,返回e
java
public class Test {
public static void main(String[] args) {
Stack<Integer> stack = new Stack<>();
stack.push(1);
stack.push(2);
stack.push(10);
System.out.println(stack);
}
}
运行结果如下
E pop() 将栈顶元素取出
E peek() 获取栈顶元素
java
public class Test {
public static void main(String[] args) {
Stack<Integer> stack = new Stack<>();
stack.push(1);
stack.push(2);
stack.push(10);
System.out.println(stack);
int ret = stack.pop();//10 ,取出栈顶元素
int ret1 = stack.peek();//2 //获取栈顶元素是多少
System.out.println(ret);
System.out.println(ret1);
System.out.println("出栈后"+stack);//出栈后,栈中数据 1 2
}
}
这里的pop是出栈的意思,而peek()只是获取其栈顶元素,并不是出栈,不会影响栈中元素
所以这里会取出栈顶元素10 而 在获取栈顶元素是2,最终栈中元素是1 2
int size() 栈的有效元素个数
boolean empty() 判断栈是否为空
java
public class Test {
public static void main(String[] args) {
Stack<Integer> stack = new Stack<>();
stack.push(1);
stack.push(2);
stack.push(3);
stack.push(5);
stack.push(11);
System.out.println(stack.size());//栈的元素个数 5
System.out.println(stack.empty());//这里栈不为空,false
}
}

栈的应用
出栈元素序列
题目:若进栈序列为 1,2,3,4 ,进栈过程中可以出栈 ,则下列不可能的⼀个出栈序列是()
A: 1,4,3,2 B: 2,3,4,1 C: 3,1,4,2 D: 3,4,2,1
答案是 C
A : 如果是1进栈,1出栈,在将1 2 3放入进去再出栈,这样出栈结果就1 4 3 2
B: 1进栈,先不出来,2 3 4依次进栈后就出栈,这样结果出栈结果为 2 3 4 1
C: 先出3 说明 1 2 3已经进栈了,3 出栈 2就是栈顶,不可以直接出1,所以错误
D 1 2 进栈,3 4分别进栈后出栈,最后出栈2 1结果为 3 4 2 1
C选项错误,所以选C
有效的括号

目的:括号是否可以左右匹配成功 "()" 或者 "([ ])"类型的都是匹配成功
思路:1创建一个Character类型的栈
2.如果遇到左边括号就将其放入栈中 ,遇到右括号就与栈顶括号元素进行匹配 ,匹配不成功就直接返回false,匹配成功就继续向后匹配,入栈重复操作
3 在匹配的时候,如果栈为空,返回false
4.最后右括号匹配完成,但是栈不为空也返回false
c
1.这里再进行匹配的时候如果栈为空说明没有其右括号左边没有左括号入栈
2.如果匹配失败直接
3.最后字符串遍历完了,但是不为空,说明栈中的左括号没有全部匹配
这上面三种情况不符合要求直接返回false
java
class Solution {
public boolean isValid(String s) {
//创建一个Character的栈
Stack<Character> stack = new Stack<>();
//遍历
for(int i = 0;i<s.length();i++){
char ch= s.charAt(i);
//左括号入栈
if(ch=='('||ch=='{'||ch=='['){
stack.push(ch);
}else{//匹配
//1.判断栈是否为空
if(stack.empty()){
return false;
}
//2.出栈进行匹配
char ch2 = stack.peek();
if(ch2=='('&&ch==')'||ch2=='['&&ch==']'||ch2=='{'&&ch=='}'){
stack.pop();
}else{
//不匹配
return false;
}
}
}
//最后如果栈不为空,说明还有没匹配的
if(!stack.empty()){
return false;
}
return true;
}
}
栈的压入、弹出序列

目的:有一个所有数都不相同的pushV数组压栈顺序 ,有一个和压栈的数相同出栈顺序 ,判断这个出栈顺序是否正确
思路:1.遍历这个pushV,将其元素进行入栈,2.并进行判断,栈顶元素是否与出栈顺序相同,相同就出栈,不相同就继续入栈,继续判断,重复操作
最后遍历完整个pushV数组,如果栈为空,说明其出栈顺序正确
c
1.这里的进行栈顶元素与popV判断明显是个while循环,因为可能连续出栈
2.并且这个循环不仅要判断是否相同也要注意栈不为空再进行判断
3.遍历完整个pushV数组后,最后如果栈为空说明出栈顺序是对的返回true,反之是false
java
import java.util.*;
public boolean IsPopOrder (int[] pushV, int[] popV) {
// write code here
Stack<Integer> stack = new Stack<>();
int j=0;//遍历弹出序列
for(int i = 0;i<pushV.length;i++){
//入栈
stack.push(pushV[i]);
//根据给出弹出的序列看看是否要出栈
while(!stack.empty()&&stack.peek()==popV[j]){
j++;
stack.pop();//出栈
}
}
//如果最后stack为空,说明成功了
return stack.empty();
}
}
逆波兰表达式
目的:给一个逆波兰表达式,求出其结果
思路:使用栈进行计算,遇到数字就入栈 ,反之就是运算符,就要出栈进行计算
c
1.这里就是遇到数字字符就进行入栈,这里注意将数字字符转为数字,
2.遇到运算符就要计算,将计算结果入栈
3.最后返回栈顶数据就是计算结果
java
class Solution {
public int evalRPN(String[] tokens) {
Stack<Integer> stack = new Stack();
for(String str: tokens){
if(!isOperator(str)){
stack.push(Integer.valueOf(str));//转换为数字入栈
}else{
//反之就出栈计算
//将计算结果入栈
int val1 = stack.pop();
int val2 = stack.pop();
switch(str){
case "+":
stack.push(val2+val1);
break;
case "-":
stack.push(val2-val1);
break;
case "*":
stack.push(val2*val1);
break;
case "/":
stack.push(val2/val1);
break;
}
}
}
return stack.pop();
}
//判断是不是运算符
private boolean isOperator(String s){
if(s.equals("+")||s.equals("-")||s.equals("*")||s.equals("/")){
return true;
}
return false;
}
}
最小栈

目的:获取其栈中最小元素
思路:就是创建两个栈,1.正常栈一个栈是正常将所有元素依靠顺序入栈,出栈
2.最小栈用来放栈中最小元素,栈顶是最小元素,这样获取最小元素的效率是O(1)


c
注意这里在入栈的时候也要将和最小栈相同的元素也要放入进去
出栈的时候,也要注意栈的最小元素可能发生变化,最小栈可能也要出栈
这时候无论如何,最小栈栈顶就是栈中最小的元素
java
class MinStack {
private Stack<Integer> stack;
private Stack<Integer> minStack;
public MinStack() {
stack = new Stack<>();
minStack = new Stack<>();
}
public void push(int val) {
//将=最小栈顶元素的值也要放入最小栈
if(minStack.empty()||val<=minStack.peek()){
minStack.push(val);
}
stack.push(val);
}
public void pop() {
//注意这里如果出栈的话,最小值可能发生变化
if(stack.peek().equals(minStack.peek())){
minStack.pop();
}
stack.pop();
}
public int top() {
return stack.peek();
}
public int getMin() {
return minStack.peek();
}
}