2026年7月30日-作业.md 8.2 KB

2026年7月30日 课后作业 — LinkedList 队列与栈操作

说明:本次作业基于今日 LinkedList 双链表课程内容,包含两道编程题 — 队列操作(Queue) 和 栈操作(Stack)。请新建 Java 项目,编写并运行代码,将运行结果截图提交。


作业 1:银行叫号系统 — Queue 队列操作

知识点:offer() / poll() / peek()、FIFO(先进先出)队列特性

场景描述:LinkedList 实现了 Queue 接口,可以用作队列(FIFO)。模拟银行叫号系统——客户先到先服务。

题目要求:

在 QueueDemo 类的 main 方法中,完成以下操作:

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 方法中,完成以下操作:

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 参考代码

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 参考代码

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());
        }
    }
}