蓝桥杯 Java B 组之链表操作(单向链表增删查改)

ops/2025/2/21 17:41:06/

Day 3:链表操作(单向链表增删查改)


 一、链表(Linked List)基础

1. 什么是链表?

链表(Linked List)是一种动态数据结构,它由一系列节点(Node) 组成,每个节点包含:

  • 数据域(value):存储数据
  • 指针域(next):指向下一个节点的引用

链表与数组的主要区别:

特性

数组(Array)

链表(Linked List)

存储方式

连续存储

离散存储

插入/删除

慢(O(n)),需移动元素

快(O(1)),直接调整指针

随机访问

快(O(1)),直接通过索引访问

慢(O(n)),需遍历

扩展性

固定大小,扩展需新建数组

动态增长,无需预分配


 二、单向链表的实现

 1. 单向链表的基本操作

我们来手写一个 单向链表(Singly Linked List),支持以下操作:

  • 插入(Insert)
  • 删除(Delete)
  • 查找(Search)
  • 更新(Update)
  • 遍历(Traversal)
// 定义链表节点类class ListNode {int value;  // 数据域ListNode next;  // 指针域,指向下一个节点public ListNode(int value) {this.value = value;this.next = null;}}// 定义单向链表class LinkedList {private ListNode head;  // 头指针// 1. 头部插入(Insert at Head)public void insertAtHead(int value) {ListNode newNode = new ListNode(value);newNode.next = head;  // 新节点指向当前头节点head = newNode;  // 更新头指针}// 2. 末尾插入(Insert at Tail)public void insertAtTail(int value) {ListNode newNode = new ListNode(value);if (head == null) {head = newNode;return;}ListNode current = head;while (current.next != null) {  // 遍历到尾节点current = current.next;}current.next = newNode;  // 尾节点指向新节点}// 3. 删除节点(Delete by Value)public void deleteByValue(int value) {if (head == null) return;  // 链表为空if (head.value == value) {  // 头节点就是目标值head = head.next;return;}ListNode current = head;while (current.next != null && current.next.value != value) {current = current.next;  // 寻找待删除节点的前一个节点}if (current.next != null) {current.next = current.next.next;  // 跳过待删除节点}}// 4. 查找节点(Search)public boolean search(int value) {ListNode current = head;while (current != null) {if (current.value == value) {return true;}current = current.next;}return false;}// 5. 更新节点(Update)public void update(int oldValue, int newValue) {ListNode current = head;while (current != null) {if (current.value == oldValue) {current.value = newValue;return;}current = current.next;}}// 6. 遍历链表(Print List)public void printList() {ListNode current = head;while (current != null) {System.out.print(current.value + " -> ");current = current.next;}System.out.println("null");}}// 测试链表功能public class LinkedListDemo {public static void main(String[] args) {LinkedList list = new LinkedList();list.insertAtHead(3);list.insertAtHead(2);list.insertAtHead(1);list.printList();  // 1 -> 2 -> 3 -> nulllist.insertAtTail(4);list.insertAtTail(5);list.printList();  // 1 -> 2 -> 3 -> 4 -> 5 -> nulllist.deleteByValue(3);list.printList();  // 1 -> 2 -> 4 -> 5 -> nullSystem.out.println(list.search(4));  // trueSystem.out.println(list.search(6));  // falselist.update(4, 10);list.printList();  // 1 -> 2 -> 10 -> 5 -> null}}


 三、链表反转(Reverse a Linked List)

1. 题目描述

给定一个单向链表,反转整个链表,使得原来的 头节点变为尾节点,尾节点变为头节点

 2. 思路分析

使用 三个指针

    1. prev(前驱)
    2. current(当前)
    3. next(后继)

逐个遍历链表,并 反转指针方向

1 -> 2 -> 3 -> null

变成:

null <- 1 <- 2 <- 3

3. 代码实现
public class ReverseLinkedList {public static ListNode reverse(ListNode head) {ListNode prev = null;ListNode current = head;while (current != null) {ListNode next = current.next;  // 记录后继节点current.next = prev;  // 反转指针prev = current;  // 更新 prevcurrent = next;  // 移动 current}return prev;  // 返回新的头节点}public static void main(String[] args) {LinkedList list = new LinkedList();list.insertAtHead(3);list.insertAtHead(2);list.insertAtHead(1);list.printList();  // 1 -> 2 -> 3 -> nulllist.head = reverse(list.head);list.printList();  // 3 -> 2 -> 1 -> null}}
  • 时间复杂度:O(n),需要遍历整个链表一次。
  • 空间复杂度:O(1),仅使用了额外的指针变量。


 四、合并两个有序链表

 1. 题目描述

给定两个递增排序的链表,合并它们成一个新的有序链表

示例:

输入:

L1: 1 -> 3 -> 5

L2: 2 -> 4 -> 6

输出:

1 -> 2 -> 3 -> 4 -> 5 -> 6

2. 代码实现
public class MergeSortedLinkedList {public static ListNode merge(ListNode l1, ListNode l2) {ListNode dummy = new ListNode(-1);ListNode current = dummy;while (l1 != null && l2 != null) {if (l1.value < l2.value) {current.next = l1;l1 = l1.next;} else {current.next = l2;l2 = l2.next;}current = current.next;}current.next = (l1 != null) ? l1 : l2;return dummy.next;}}
  • 时间复杂度:O(n + m),遍历两个链表一次。
  • 空间复杂度:O(1),不使用额外存储,仅修改指针。


常考点:

链表反转:理解如何通过指针操作反转链表。

合并有序链表:理解如何合并两个有序链表。

链表的基本操作:插入、删除、查找、修改节点。

指针操作:理解指针的移动和修改。

易错点:

指针操作错误:容易在指针操作时忘记更新指针,导致链表断裂。

边界条件:容易忽略链表为空或只有一个节点的情况。

链表断裂:在删除或插入节点时,容易忘记更新前一个节点的指针。

合并链表时的剩余部分:容易忘记将剩余部分接到结果链表的末尾。 五、总结与易错点


http://www.ppmy.cn/ops/159841.html

相关文章

rustdesk编译修改名字

最近&#xff0c;我用Rust重写了一个2W行C代码的linux内核模块。在此记录一点经验。我此前没写过内核模块&#xff0c;认识比较疏浅&#xff0c;有错误欢迎指正。 为什么要重写&#xff1f; 这个模块2W行代码量看起来不多&#xff0c;却在线上时常故障&#xff0c;永远改不完。…

【kafka系列】broker

目录 Broker 接收生产者消息和返回消息给消费者的流程逻辑分析 Broker 处理生产者消息的核心流程 Broker 处理消费者消息的核心流程 关键点总结 Broker 接收生产者消息和返回消息给消费者的流程逻辑分析 Broker 处理生产者消息的核心流程 接收请求 Broker 的 SocketServer …

rust笔记1-学习资料推荐

学习Rust的Trait、生命周期和模式确实需要一些时间&#xff0c;尤其是当这些概念在其他语言中不常见时。以下是一些学习资料和建议&#xff0c;帮助你更好地理解这些概念&#xff1a; 1. 官方文档与书籍 《The Rust Programming Language》&#xff08;俗称“The Book”&…

【大模型】DeepSeek 高级提示词技巧使用详解

目录 一、前言 二、DeepSeek 通用提示词技巧 2.1 DeepSeek 通用提示词技巧总结 三、DeepSeek 进阶使用技巧 3.1 DeepSeek一个特定角色的人设 3.1.1 为DeepSeek设置角色操作案例一 3.1.2 为DeepSeek设置角色操作案例二 3.2 DeepSeek开放人设升级 3.2.1 特殊的人设&#…

filebeat抓取nginx日志

目录 一、抓取普通的应用输出日志到elasticsearch 二、抓取nginx日志输出到ElasticSearch 2.1、nginx.conf设定日志输出为JSON格式 2.2、nginx.conf设定日志按天输出文件 2.3、抓取Nginx JSON到ElasticSearch配置 一、抓取普通的应用输出日志到elasticsearch - type: log…

拯救者电脑在重装系统之后电源计划丢失Fn+Q切换不了模式怎么恢复?

参考联想知识库的一下链接&#xff1a; https://iknow.lenovo.com.cn/detail/196192 其中下载的解压文件后的文件需要复制粘贴到D盘的根目录下&#xff0c;再来运行文件。若在生成的log文件中看到导入成功以及控制面板中看到已添加的电源计划即可 如果还是无效可是试试以下的…

PHP 可用的函数

PHP 可用的函数 引言 PHP是一种广泛使用的开源服务器端脚本语言,被用于开发各种动态网站和应用程序。PHP函数是其核心组成部分,提供了丰富的功能来帮助开发者构建复杂的系统。本文将详细介绍PHP中可用的函数,并按照功能分类进行阐述。 常用函数 数据类型转换函数 int():…

GIT:如何合并已commit的信息并进行push操作

在Git中合并已提交(commit)的信息并进行推送(push)操作是一个常见的需求&#xff0c;特别是在需要整理提交历史或合并多个小更改以保持项目历史清晰时。以下是一个详细的步骤说明&#xff0c;旨在提供一个清晰、专业的指南&#xff0c;以帮助您实现这一目标。 1. 审查提交历史…