1.栈:一种先进后出的结构,常见实现方式采用线性结构。
(1)栈的相关操作:
push(e);压栈
e = pop();弹出栈顶元素
e = peek();查看栈顶元素
(2)使用栈的场景:反向队列;回溯;深度优先遍历。
(3)实现栈
2.队列:一种先见先出的结构,常见实现方式采用线性结构。
(1)队列的相关操作:
offer(e);将元素放入队列
e = poll();从队列中取出元素
e = peek();查看队首元素
(2)使用队列的场景:保证公平性;广度优先遍历。
(3)实现队列
3.实现栈和队列相关应用的例题
(1)括号匹配问题(来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/valid-parentheses
题目介绍:给定一个只包括 '(',')','{','}','[',']' 的字符串 s ,判断字符串是否有效。
有效字符串需满足:左括号必须用相同类型的右括号闭合;左括号必须以正确的顺序闭合。
题目分析:
代码实现:
public boolean isValid(String s){
Deque<Character> stack = new LinkedList<>();
for(char ch : s.toCharArray()){
if(isLeft(ch)){
stack.push(ch);
}else{
if(stack.isEmpty()){
return false;
}
char left = stack.pop();
if(!isMatch(left,ch)){
return false;
}
}
}
return stack.isEmpty();
}
private boolean isLeft(char ch) {
return ch == '(' || ch == '[' || ch == '{';
}
private boolean isMatch(char left, char right) {
if(left == '{' && right == '}'){
return true;
}
if(left == '[' && right == ']'){
return true;
}
if(left == '(' && right == ')'){
return true;
}
return false;
}
(2)用队列实现栈(来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/implement-stack-using-queues)
题目介绍:请你仅使用两个队列实现一个后入先出(LIFO)的栈
,并支持普通栈的全部四种操作(push、top、pop 和 empty)。
实现 MyStack 类:
void push(int x) 将元素 x 压入栈顶。
int pop() 移除并返回栈顶元素。
int top() 返回栈顶元素。
boolean empty() 如果栈是空的,返回 true ;否则,返回 false 。
题目分析:
代码实现:
public class MyStack{
//使用两个队列实现一个栈
private final Queue<Integer> queue1 = new LinkedList<>();
private final Queue<Integer> queue2 = new LinkedList<>();
public MyStack(){}
public void push(int x) {
queue1.offer(x);
}
public int pop() {
int size = queue1.size();
for(int i = 0;i < size - 1;i++){
int e = queue1.poll();
queue2.offer(e);
}
int r = queue1.poll();
for(int i = 0;i <size - 1;i++){
int e = queue2.poll();
queue1.offer(e);
}
return r;
}
public int top() {
int size = queue1.size();
for(int i = 0;i < size - 1;i++){
int e = queue1.poll();
queue2.offer(e);
}
int r = queue1.poll();
for(int i = 0;i <size - 1;i++){
int e = queue2.poll();
queue1.offer(e);
}
queue1.offer(r);
return r;
}
public boolean empty() {
return queue1.isEmpty();
}
}
(3)用栈实现队列(来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/implement-queue-using-stacks)
题目介绍:请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push、pop、peek、empty):
实现 MyQueue 类:
void push(int x) 将元素 x 推到队列的末尾
int pop() 从队列的开头移除并返回元素
int peek() 返回队列开头的元素
boolean empty() 如果队列为空,返回 true ;否则,返回 false
题目分析:
代码实现:
public class MyQueue{
private final Deque<Integer> stack1 = new LinkedList<>();
private final Deque<Integer> stack2 = new LinkedList<>();
public MyQueue() {
}
public void push(int x) {
stack2.push(x);
}
public int pop() {
if(stack1.isEmpty()){
while(!stack2.isEmpty()){
int e = stack2.pop();
stack1.push(e);
}
}
return stack1.pop();
}
public int peek() {
if(stack1.isEmpty()){
while(!stack2.isEmpty()){
int e = stack2.pop();
stack1.push(e);
}
}
return stack1.peek();
}
public boolean empty() {
return stack1.isEmpty() && stack2.isEmpty();
}
}
(4)最小栈(来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/min-stack)
题目介绍:设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。
实现 MinStack 类:
MinStack() 初始化堆栈对象。
void push(int val) 将元素val推入堆栈。
void pop() 删除堆栈顶部的元素。
int top() 获取堆栈顶部的元素。
int getMin() 获取堆栈中的最小元素。
题目分析:
代码实现:
public class MinStack {
private final Deque<Integer> stack1 = new LinkedList<>();
private final Deque<Integer> stack2 = new LinkedList<>();
public MinStack() {}
public void push(int val) {
stack1.push(val);
if(stack2.isEmpty() || val < stack2.peek()){
stack2.push(val);
}else{
stack2.push(stack2.peek());
}
}
public void pop() {
stack1.pop();
stack2.pop();
}
public int top() {
return stack1.peek();
}
public int getMin() {
return stack2.peek();
}
}
(5)设计循环队列(来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/design-circular-queue)
题目介绍:实现以下方法
MyCircularQueue(k): 构造器,设置队列长度为 k 。
Front: 从队首获取元素。如果队列为空,返回 -1 。
Rear: 获取队尾元素。如果队列为空,返回 -1 。
enQueue(value): 向循环队列插入一个元素。如果成功插入则返回真。
deQueue(): 从循环队列中删除一个元素。如果成功删除则返回真。
isEmpty(): 检查循环队列是否为空。
isFull(): 检查循环队列是否已满。
题目分析:
代码实现:
public class MyCircularQueue {
private int[] array;
private int size;
private int frontIndex;
private int rearIndex;
public MyCircularQueue(int k) {
array = new int[k];
}
public boolean enQueue(int value) {
if(isFull()){
return false;
}
array[rearIndex] = value;
rearIndex = (rearIndex + 1) % array.length;
size++;
return true;
}
public boolean deQueue() {
if(isEmpty()){
return false;
}
frontIndex = (frontIndex + 1) % array.length;
size--;
return true;
}
public int Front() {
if(isEmpty()){
return -1;
}
return array[frontIndex];
}
public int Rear() {
if(isEmpty()){
return -1;
}
int index = (rearIndex - 1 + array.length) % array.length;
return array[index];
}
public boolean isEmpty() {
return size == 0;
}
public boolean isFull() {
return size == array.length;
}
}