c/c++蓝桥杯经典编程题100道(16)链表反转

news/2025/2/10 21:23:06/

链表反转

c/c++蓝桥杯经典编程题100道-目录-CSDN博客


目录

链表反转

一、题型解释

二、例题问题描述

三、C语言实现

解法1:迭代反转(难度★)

解法2:递归反转(难度★★)

解法3:分组反转(难度★★★)

四、C++实现

解法1:迭代反转(难度★)

解法2:使用STL容器辅助(难度★★)

五、总结对比表

六、特殊方法与内置函数补充

1. C++智能指针

2. 链表调试技巧


一、题型解释

链表反转是将链表节点的连接方向完全逆序的操作。常见题型:

  1. 基础反转:反转整个单链表(如 1→2→3→4→5 转为 5→4→3→2→1)。

  2. 部分反转:反转链表的某个区间(如反转第2到第4个节点)。

  3. 分组反转:每k个节点为一组进行反转(如k=2时,1→2→3→4→5 转为 2→1→4→3→5)。

  4. 递归反转:用递归思想实现链表反转。


二、例题问题描述

例题1:输入链表 1→2→3→4→5,输出反转后的链表 5→4→3→2→1
例题2:输入链表 1→2→3→4→5 和区间 [2,4],输出 1→4→3→2→5
例题3:输入链表 1→2→3→4→5 和k=2,输出 2→1→4→3→5
例题4:输入链表 1→2,输出 2→1


三、C语言实现

解法1:迭代反转(难度★)

通俗解释

  • 像翻书一样,逐个节点改变指针方向,将当前节点的next指向前一个节点。

c

#include <stdio.h>
#include <stdlib.h>struct ListNode {int val;struct ListNode *next;
};// 迭代反转链表
struct ListNode* reverseList(struct ListNode* head) {struct ListNode *prev = NULL, *curr = head;while (curr != NULL) {struct ListNode *nextTemp = curr->next; // 保存下一个节点curr->next = prev; // 当前节点指向前一个节点prev = curr;       // 前一个节点后移curr = nextTemp;   // 当前节点后移}return prev; // prev最终指向新链表的头节点
}// 打印链表
void printList(struct ListNode* head) {while (head != NULL) {printf("%d→", head->val);head = head->next;}printf("NULL\n");
}int main() {// 构建链表 1→2→3→4→5struct ListNode node5 = {5, NULL};struct ListNode node4 = {4, &node5};struct ListNode node3 = {3, &node4};struct ListNode node2 = {2, &node3};struct ListNode node1 = {1, &node2};struct ListNode* newHead = reverseList(&node1);printList(newHead); // 输出 5→4→3→2→1→NULLreturn 0;
}

代码逻辑

  1. 初始化指针prev(前一个节点)初始为NULL,curr(当前节点)初始为头节点。

  2. 循环操作

    • 保存下一个节点 nextTemp = curr->next

    • 将当前节点的 next 指向 prev

    • prev 和 curr 向后移动。

  3. 终止条件:当 curr 为NULL时,prev 成为新链表的头节点。


解法2:递归反转(难度★★)

通俗解释

  • 假设后面的链表已经反转,只需处理当前节点和已反转部分的连接。

c

struct ListNode* reverseListRecursive(struct ListNode* head) {if (head == NULL || head->next == NULL) {return head; // 基线条件:空链表或只剩一个节点}struct ListNode* newHead = reverseListRecursive(head->next); // 递归反转后续链表head->next->next = head; // 当前节点的下一个节点指向自己(反转方向)head->next = NULL;       // 断开原有连接return newHead; // 返回新头节点
}int main() {// 测试递归反转struct ListNode* newHead = reverseListRecursive(&node1);printList(newHead); // 输出 5→4→3→2→1→NULLreturn 0;
}

代码逻辑

  1. 基线条件:链表为空或只剩一个节点时直接返回。

  2. 递归调用:先反转 head->next 之后的链表,得到新头节点 newHead

  3. 反转当前节点:将当前节点的下一个节点的 next 指向自己,再断开自己的 next

  4. 递归栈展开:从最后一个节点开始逐层反转。


解法3:分组反转(难度★★★)

通俗解释

  • 每k个节点为一组,组内反转,若剩余节点不足k个则保持原顺序。

c

struct ListNode* reverseKGroup(struct ListNode* head, int k) {struct ListNode *curr = head;int count = 0;// 检查是否足够k个节点while (curr != NULL && count < k) {curr = curr->next;count++;}if (count == k) { // 足够k个节点时反转struct ListNode *prev = reverseKGroup(curr, k); // 递归处理后续分组// 反转当前k个节点while (count-- > 0) {struct ListNode *nextTemp = head->next;head->next = prev;prev = head;head = nextTemp;}head = prev;}return head; // 不足k个时直接返回原头节点
}int main() {// 测试分组反转(k=2)struct ListNode* newHead = reverseKGroup(&node1, 2);printList(newHead); // 输出 2→1→4→3→5→NULLreturn 0;
}

代码逻辑

  1. 检查分组长度:遍历链表,判断剩余节点是否足够k个。

  2. 递归处理后续分组:若足够,递归反转后续链表,返回已反转部分的头节点。

  3. 反转当前分组:用迭代法反转当前k个节点,连接到已反转部分。

  4. 终止条件:若不足k个,直接返回当前头节点。


四、C++实现

解法1:迭代反转(难度★)

通俗解释

  • 与C语言迭代法逻辑相同,使用指针操作。

cpp

#include <iostream>
using namespace std;struct ListNode {int val;ListNode *next;ListNode(int x) : val(x), next(NULL) {}
};class Solution {
public:ListNode* reverseList(ListNode* head) {ListNode *prev = NULL, *curr = head;while (curr != NULL) {ListNode *nextTemp = curr->next;curr->next = prev;prev = curr;curr = nextTemp;}return prev;}
};int main() {ListNode *head = new ListNode(1);head->next = new ListNode(2);head->next->next = new ListNode(3);head->next->next->next = new ListNode(4);head->next->next->next->next = new ListNode(5);Solution sol;ListNode *newHead = sol.reverseList(head);while (newHead != NULL) {cout << newHead->val << "→";newHead = newHead->next;}cout << "NULL" << endl; // 输出 5→4→3→2→1→NULLreturn 0;
}

代码逻辑

  • 与C语言版本完全一致,但使用C++的类和对象封装。


解法2:使用STL容器辅助(难度★★)

通俗解释

  • 将链表存入容器(如栈或数组),反向构建新链表。

cpp

ListNode* reverseListSTL(ListNode* head) {vector<int> values;ListNode *curr = head;while (curr != NULL) { // 存入数组values.push_back(curr->val);curr = curr->next;}ListNode *dummy = new ListNode(0);curr = dummy;for (int i = values.size() - 1; i >= 0; i--) { // 反向遍历数组curr->next = new ListNode(values[i]);curr = curr->next;}return dummy->next;
}int main() {ListNode *head = new ListNode(1);head->next = new ListNode(2);head->next->next = new ListNode(3);ListNode *newHead = reverseListSTL(head);// 输出 3→2→1→NULLreturn 0;
}

代码逻辑

  1. 存储节点值:遍历链表,将节点的值存入数组。

  2. 反向构建链表:从数组末尾开始遍历,创建新节点并连接。

  3. 优点:代码简单,但空间复杂度为O(n)。


五、总结对比表

方法时间复杂度空间复杂度优点缺点
迭代反转O(n)O(1)高效,无需额外空间需处理多个指针
递归反转O(n)O(n)代码简洁栈空间消耗大
分组反转O(n)O(1)支持复杂需求实现较复杂
STL容器辅助O(n)O(n)代码简单空间效率低

六、特殊方法与内置函数补充

1. C++智能指针

  • 作用:自动管理内存,避免内存泄漏(需包含 <memory> 头文件)。

  • 示例

    shared_ptr<ListNode> node = make_shared<ListNode>(1);

2. 链表调试技巧

  • 打印链表:编写打印函数时,可在每个节点后添加箭头(),末尾标记 NULL

  • 图形化工具:使用在线数据结构可视化工具(如VisuAlgo)辅助调试。

c/c++蓝桥杯经典编程题100道-目录-CSDN博客


http://www.ppmy.cn/news/1570964.html

相关文章

基于STM32的智能鱼缸水质净化系统设计

&#x1f91e;&#x1f91e;大家好&#xff0c;这里是5132单片机毕设设计项目分享&#xff0c;今天给大家分享的是智能鱼缸水质净化系统。 目录 1、设计要求 2、系统功能 3、演示视频和实物 4、系统设计框图 5、软件设计流程图 6、原理图 7、主程序 8、总结 1、设计要求…

大模型deepseek-r1 本地快速搭建

1、安装部署ollama 详细步骤见&#xff1a;Ollama 下载和安装 官网下载地址&#xff1a;Ollama官网 2、大模型Deepseekk-r1下载 详细步骤见&#xff1a;大模型deepseek-r1 本地ollama部署详解 ollama run deepseek-r13、Open WebUI部署详解 详细见步骤&#xff1a;大模型d…

PHP 完整表单实例

PHP 完整表单实例 引言 表单是网站与用户交互的重要方式&#xff0c;尤其是在收集用户输入数据时。PHP 作为一种流行的服务器端脚本语言&#xff0c;在处理表单数据方面具有强大的功能。本文将提供一个完整的 PHP 表单实例&#xff0c;涵盖表单创建、数据收集、验证和存储等关…

如何通过Deepseek的API进行开发和使用(适合开发者和小白的学习使用教程)

目录 一,API创建与获取 二,直接进行API的调用 2.1 安装第三方库 2.2 官方支持的接口调用方式 2.3 编写的小tips 2.4 AI助手工具代码 三, 配置方面的说明 3.1 token价格和字符用量 3.2 响应错误码 最近在休息的时候也是一直会刷到关于deepseek,简单使用了一下,发现这…

Spring JDBC模块解析 -深入SqlParameterSource

在前面的博客中&#xff0c;我们探讨了Spring Data Access Module中的主要组件&#xff1a; JdbcTemplate和SimpleJdbcInsert。在这两部分的基础上&#xff0c;我们将继续探讨更详细 的用法&#xff0c;包括如何使用RowMapper和SqlParameterSource等高级主题。 JdbcTemplate …

Vue2常用指令

一、指令基础概念 在 Vue2 里&#xff0c;指令是带有 v- 前缀的特殊属性。它的主要作用是当表达式的值发生变化时&#xff0c;会相应地将某些特殊的行为应用到 DOM 上。简单来说&#xff0c;指令就是 Vue 提供的一种便捷语法&#xff0c;让我们可以更轻松地操作 DOM 和实现业务…

【翻译+论文阅读】DeepSeek-R1评测:粉碎GPT-4和Claude 3.5的开源AI革命

目录 一、DeepSeek-R1 势不可挡二、DeepSeek-R1 卓越之处三、DeepSeek-R1 创新设计四、DeepSeek-R1 进化之路1. 强化学习RL代替监督微调学习SFL2. Aha Moment “啊哈”时刻3. 蒸馏版本仅采用SFT4. 未来研究计划 部分内容有拓展&#xff0c;部分内容有删除&#xff0c;与原文会有…

Unity3D开发之2019.4.5f1版本IPointerClickHandler Bug

实际代码测试ui物体挂载的脚本里&#xff1a; 如果实现IPointerDownHandler和IPointerClickHandler接口&#xff0c;则会触发OnPointerClick和OnPointerDown函数调用。如果只实现IPointerClickHandler接口&#xff0c;则不会触发OnPointerClick函数调用。如果只实现IPointerDo…