Browse Source

feat: 新增20260730课后作业——LinkedList队列操作(Queue银行叫号系统)与栈操作(Stack浏览器后退功能)

WanJL 3 weeks ago
parent
commit
deb693858c
1 changed files with 245 additions and 0 deletions
  1. 245 0
      课后作业/2026年7月30日-作业.md

+ 245 - 0
课后作业/2026年7月30日-作业.md

@@ -0,0 +1,245 @@
+# 2026年7月30日 课后作业 — LinkedList 队列与栈操作
+
+> **说明**:本次作业基于今日 LinkedList 双链表课程内容,包含两道编程题 — **队列操作(Queue)** 和 **栈操作(Stack)**。请新建 Java 项目,编写并运行代码,将运行结果截图提交。
+
+---
+
+## 作业 1:银行叫号系统 — Queue 队列操作
+
+**知识点**:`offer()` / `poll()` / `peek()`、FIFO(先进先出)队列特性
+
+**场景描述**:LinkedList 实现了 `Queue` 接口,可以用作**队列(FIFO)**。模拟银行叫号系统——客户先到先服务。
+
+**题目要求**:
+
+在 `QueueDemo` 类的 `main` 方法中,完成以下操作:
+
+```java
+import java.util.LinkedList;
+import java.util.Queue;
+
+public class QueueDemo {
+    public static void main(String[] args) {
+        // 1. 创建一个 Queue<String>,使用 LinkedList 实现
+        //    提示:Queue<String> queue = new LinkedList<>();
+
+        // 2. 三个客户依次取号排队:
+        //    "客户A" → offer() 入队
+        //    "客户B" → offer() 入队
+        //    "客户C" → offer() 入队
+
+        // 3. 查看当前排队人数(size())
+
+        // 4. 查看队首是谁但不离开队列(peek())
+        //    输出:"当前排队人数:3,队首:客户A"
+
+        // 5. 叫号服务:队首"客户A"出队(poll())
+        //    输出:"请客户A前往1号窗口"
+
+        // 6. 新客户"客户D"取号排队
+
+        // 7. 再次叫号:队首"客户B"出队
+        //    输出:"请客户B前往1号窗口"
+
+        // 8. 输出剩余排队客户
+        //    输出:"剩余排队客户:[客户C, 客户D]"
+
+        // 9. 演示 poll() 与 peek() 的空队列安全行为:
+        //    创建一个空队列,调用 poll() 和 peek()
+        //    观察它们返回什么,而不是抛异常
+    }
+}
+```
+
+**预期输出**:
+```
+当前排队人数:3,队首:客户A
+请客户A前往1号窗口
+请客户B前往1号窗口
+剩余排队客户:[客户C, 客户D]
+空队列 poll() 返回:null
+空队列 peek() 返回:null
+```
+
+**Queue 方法对比**:
+
+| 操作 | 抛出异常 | 返回特殊值 |
+|------|----------|-----------|
+| 插入 | `add(e)` | `offer(e)` |
+| 移除 | `remove()` | `poll()` |
+| 查看 | `element()` | `peek()` |
+
+**思考题**(选做,不要求提交代码):
+1. `poll()` 和 `remove()` 在空队列时行为有什么不同?
+2. 队列的 FIFO 特性和栈的 LIFO 特性在实际开发中分别适用于什么场景?
+
+---
+
+## 作业 2:浏览器后退功能 — Stack 栈操作
+
+**知识点**:`push()` / `pop()` / `peek()`、LIFO(后进先出)栈特性、`Deque` 接口的栈语义
+
+**场景描述**:LinkedList 实现了 `Deque` 接口,而 `Deque` 提供了完整的**栈(Stack)操作**。Java 官方建议:**使用 `Deque` 代替 `Stack` 类**,因为 `Stack` 继承自 `Vector`,性能较差且线程安全开销不必要。模拟一个"浏览器后退"功能——每次访问新页面就入栈,点击后退就从栈顶弹出。
+
+**题目要求**:
+
+在 `StackDemo` 类的 `main` 方法中,完成以下操作:
+
+```java
+import java.util.Deque;
+import java.util.LinkedList;
+
+public class StackDemo {
+    public static void main(String[] args) {
+        // 1. 创建一个 Deque<String>,使用 LinkedList 实现,作为栈使用
+        //    提示:Deque<String> stack = new LinkedList<>();
+
+        // 2. 模拟小明浏览网页:
+        //    "首页" → push() 入栈
+        //    "新闻页" → push() 入栈
+        //    "体育频道" → push() 入栈
+        //    "NBA战报" → push() 入栈
+
+        // 3. 查看当前栈顶页面(peek()),不弹出
+        //    输出:"当前页面:NBA战报"
+
+        // 4. 点击后退:依次弹出 3 次(pop())
+        //    每次输出:"后退到:XXX"
+        //    顺序应该是:NBA战报 → 体育频道 → 新闻页
+
+        // 5. 输出栈中剩余页面
+        //    输出:"剩余浏览记录:[首页]"
+
+        // 6. 小明又访问了新页面:"科技频道" → push()
+        //    "AI专题" → push()
+
+        // 7. 再次查看栈顶(peek())
+
+        // 8. 连续弹出所有页面(用循环 pop() 直到栈为空)
+        //    提示:while (!stack.isEmpty()) { ... }
+
+        // 9. 尝试在空栈时调用 pop(),观察发生了什么
+        //    提示:NoSuchElementException(与 Queue 的 poll() 不同)
+    }
+}
+```
+
+**预期输出**:
+```
+========== 浏览器后退模拟 ==========
+当前页面:NBA战报
+后退到:NBA战报
+后退到:体育频道
+后退到:新闻页
+剩余浏览记录:[首页]
+当前页面:AI专题
+连续后退:
+后退到:AI专题
+后退到:科技频道
+后退到:首页
+浏览记录已清空
+```
+
+**关键方法说明**:
+
+| 方法 | 栈的等价操作 | 说明 |
+|------|-------------|------|
+| `push(E e)` | 入栈(压栈) | 将元素压入栈顶,等价于 `addFirst()` |
+| `pop()` | 出栈(弹栈) | 移除并返回栈顶元素,空栈时抛 `NoSuchElementException` |
+| `peek()` | 查看栈顶 | 返回栈顶元素但不移除,空栈时抛 `NoSuchElementException` |
+
+**LinkedList 三种角色对比**:
+
+| 角色 | 接口 | 核心操作 | 数据结构 |
+|------|------|---------|---------|
+| 列表(List) | `List` | `add()` / `get()` / `set()` / `remove(index)` | 线性表 |
+| 队列(Queue) | `Queue` | `offer()` / `poll()` / `peek()` | FIFO 先进先出 |
+| 栈(Stack) | `Deque` | `push()` / `pop()` / `peek()` | LIFO 后进先出 |
+
+**思考题**(选做,不要求提交代码):
+1. Java 官方为什么不推荐使用 `java.util.Stack` 类?
+2. `Deque` 的 `push()` 和 `addFirst()` 本质上是同一个方法,为什么提供两个名字?
+3. 用 `Deque` 实现栈时,`pop()` 和 `poll()` 在空栈时行为有何不同?
+
+---
+
+## 提交要求
+
+1. 新建 Java 项目(或使用现有项目),包名建议:`homework0730`
+2. 编写 `QueueDemo` 和 `StackDemo` 两个类,分别实现作业 1 和作业 2
+3. 运行代码,控制台输出结果需与预期输出一致
+4. **将代码源文件和运行结果截图**提交到班级群
+
+## 参考答案(供批改参考)
+
+### 作业 1 参考代码
+
+```java
+import java.util.LinkedList;
+import java.util.Queue;
+
+public class QueueDemo {
+    public static void main(String[] args) {
+        Queue<String> queue = new LinkedList<>();
+
+        queue.offer("客户A");
+        queue.offer("客户B");
+        queue.offer("客户C");
+
+        System.out.println("当前排队人数:" + queue.size()
+            + ",队首:" + queue.peek());
+
+        System.out.println("请" + queue.poll() + "前往1号窗口");
+        queue.offer("客户D");
+        System.out.println("请" + queue.poll() + "前往1号窗口");
+        System.out.println("剩余排队客户:" + queue);
+
+        Queue<String> emptyQueue = new LinkedList<>();
+        System.out.println("空队列 poll() 返回:" + emptyQueue.poll());
+        System.out.println("空队列 peek() 返回:" + emptyQueue.peek());
+    }
+}
+```
+
+### 作业 2 参考代码
+
+```java
+import java.util.Deque;
+import java.util.LinkedList;
+
+public class StackDemo {
+    public static void main(String[] args) {
+        Deque<String> stack = new LinkedList<>();
+
+        stack.push("首页");
+        stack.push("新闻页");
+        stack.push("体育频道");
+        stack.push("NBA战报");
+
+        System.out.println("当前页面:" + stack.peek());
+
+        System.out.println("后退到:" + stack.pop());
+        System.out.println("后退到:" + stack.pop());
+        System.out.println("后退到:" + stack.pop());
+
+        System.out.println("剩余浏览记录:" + stack);
+
+        stack.push("科技频道");
+        stack.push("AI专题");
+        System.out.println("当前页面:" + stack.peek());
+
+        System.out.println("连续后退:");
+        while (!stack.isEmpty()) {
+            System.out.println("后退到:" + stack.pop());
+        }
+        System.out.println("浏览记录已清空");
+
+        Deque<String> emptyStack = new LinkedList<>();
+        try {
+            emptyStack.pop();
+        } catch (Exception e) {
+            System.out.println("空栈调用 pop():" + e.getClass().getSimpleName());
+        }
+    }
+}
+```