【本节目标】
- 栈的概念及使用
- 队列的概念及使用

一、栈(Stack):后进先出(LIFO)的数据结构
1.1 栈的基本概念
栈是一种遵循后进先出(Last In First Out, LIFO)原则的线性数据结构。想象一叠盘子,你总是把新盘子放在最上面(LI),取盘子时也从最上面开始取(FO)。

1.2 栈的核心操作
栈通常支持以下几种基本操作:
- push:将元素压入栈顶
- pop:移除并返回栈顶元素
- peek/top:查看栈顶元素但不移除
- isEmpty:检查栈是否为空
- size:获取栈中元素数量
public static void main(String[] args) {
MyStack stack = new MyStack();
stack.push(12);
stack.push(23);
stack.push(34);
stack.push(45);
System.out.println(stack.pop());//12
System.out.println(stack.pop());//23
System.out.println(stack.pop());//34
System.out.println("=========");
System.out.println(stack.peek());//45
}
1.3 栈的模拟实现
从上图中可以看到,Stack继承了Vector,Vector和ArrayList类似,都是动态的顺序表,不同的是Vector是线程安全的。

public class MyStack {
public int[] elem;
public int usedSize;
public MyStack() {
this.elem = new int[10];
}
public void push(int val){
if (isFull()){
this.elem = Arrays.copyOf(elem,2*elem.length);
}
elem[usedSize++] = val;
}
public boolean isFull(){
return usedSize == elem.length;
}
public int pop(){
if (isFull()){
throw new EmptyStackException();
}
int val = elem[usedSize - 1];
usedSize--;
return val;
}
public int peek(){
if (isEmpty()){
throw new EmptyStackException();
}
return elem[usedSize - 1];
}
public boolean isEmpty(){
return usedSize == 0;
}
}
二、队列(Queue):先进先出(FIFO)的数据结构
2.1 队列的基本概念
队列是一种遵循先进先出(First In First Out, FIFO)原则的线性数据结构。想象排队买票,先来的人先得到服务(FI),后来的人排在队尾(FO)。
注意:Queue是个接口,在实例化时必须实例化LinkedList的对象,因为LinkedList实现了Queue接口。

2.2 队列的核心操作
队列通常支持以下几种基本操作:
- enqueue:将元素加入队尾
- dequeue:移除并返回队首元素
- front/peek:查看队首元素但不移除
- isEmpty:检查队列是否为空
- size:获取队列中元素数量
public static void main4(String[] args) {
Queue<Integer> queue = new LinkedList<>();
LinkedList<Integer> queue2 = new LinkedList<>();
queue.offer(1);
queue.offer(2);
queue.offer(3);
queue.offer(4);
System.out.println(queue.poll());//1
System.out.println(queue.peek());//2
}
2.3 队列模拟实现

public class MyQueue {
static class ListNode{
public int val;
public ListNode prev;
public ListNode next;
public ListNode(int val) {
this.val = val;
}
}
public ListNode first = null;
public ListNode last = null;
public int usedSize = 0;
public void offer(int val){
ListNode node = new ListNode(val);
if (isEmpty()){
first = last = node;
}else{
last.next = node;
node.prev = last;
last = last.next;
}
usedSize++;
}
public int poll(){
if (isEmpty()){
return -1;
}
int val = first.val;
first = first.next;
if (first != null){
first.prev = null;
}
return val;
}
public int peek(){
if (isEmpty()){
return -1;
}
return first.val;
}
public boolean isEmpty(){
return usedSize == 0;
// return first == null;
}
}
2.4 循环队列
实际中我们有时还会使用一种队列叫循环队列。如操作系统课程讲解生产者消费者模型时可以就会使用循环队列。 环形队列通常使用数组实现。

如何区分空与满
- 通过添加 size 属性记录
- 保留一个位置
- 使用标记
三.双端队列 (Deque)
是指允许两端都可以进行入队和出队操作的队列,deque 是 “double ended queue” 的简称。 那就说明元素可以从队头出队和入队,也可以从队尾出队和入队。
Deque是一个接口,使用时必须创建LinkedList的对象。

四、栈与队列的比较
| 特性 | 栈(Stack) | 队列(Queue) |
|---|---|---|
| 原则 | LIFO (后进先出) | FIFO (先进先出) |
| 插入操作 | push (栈顶) | enqueue (队尾) |
| 删除操作 | pop (栈顶) | dequeue (队首) |
| 访问操作 | peek (栈顶) | front (队首) |
| 典型应用 | 函数调用、撤销操作、DFS | 任务调度、消息队列、BFS |
| 实现复杂度 | 相对简单 | 需要考虑队首和队尾 |
4810

被折叠的 条评论
为什么被折叠?



