C语言——链表指定区间反转

目录

1.创建一个链表

1.链表节点定义

2.创建新节点

3.链表生成(输入)

4.链表输出

2.链表指定区间反转函数

1.创建哑节点

2.找到第m-1位的节点,开始 反转

3.连接反转后的链表与未反转的链表

3.未使用哑节点的运行结果

这段代码可以直接运行检测结果

1.创建一个链表

1.链表节点定义

#include <stdio.h>
#include <stdlib.h>// 链表节点定义
struct ListNode {int val;struct ListNode* next;
};

2.创建新节点

// 创建新节点
struct ListNode* createNode(int value) {struct ListNode* newNode = (struct ListNode*)malloc(sizeof(struct ListNode));if (newNode == NULL) {printf("内存分配失败!\n");exit(1);}newNode->val = value;newNode->next = NULL;return newNode;
}

3.链表生成(输入)

// 从数组创建链表
struct ListNode* createListFromArray(int arr[], int size) {if (size == 0) return NULL;struct ListNode* head = createNode(arr[0]);struct ListNode* current = head;for (int i = 1; i < size; i++) {current->next = createNode(arr[i]);current = current->next;}return head;
}// 交互式输入创建链表
struct ListNode* createListInteractive() {int n, value;printf("请输入链表节点个数: ");scanf("%d", &n);if (n <= 0) return NULL;printf("请输入%d个节点的值:\n", n);scanf("%d", &value);struct ListNode* head = createNode(value);struct ListNode* current = head;for (int i = 1; i < n; i++) {scanf("%d", &value);current->next = createNode(value);current = current->next;}return head;
}

4.链表输出

// 打印链表
void printList(struct ListNode* head) {struct ListNode* current = head;printf("链表: ");while (current != NULL) {printf("%d", current->val);if (current->next != NULL) {printf(" → ");}current = current->next;}printf(" → NULL\n");
}// 带详细信息的打印
void printListDetailed(struct ListNode* head) {struct ListNode* current = head;int count = 1;printf("链表详细信息:\n");printf("地址       值   下一个节点\n");printf("-------------------------\n");while (current != NULL) {printf("%p  %2d  ", (void*)current, current->val);if (current->next != NULL) {printf("%p", (void*)current->next);} else {printf("NULL");}printf("\n");current = current->next;count++;}printf("-------------------------\n");
}

2.链表指定区间反转函数

struct ListNode* reverseBetween(struct ListNode* head, int m, int n) {if (head == NULL || m == n) return head;// 创建哑节点 - 关键步骤!struct ListNode dummy;dummy.next = head;struct ListNode* pre = &dummy;// 移动到第 m-1 个节点for (int i = 1; i < m; i++) {pre = pre->next;}// 反转 m 到 n 的节点struct ListNode* cur = pre->next;struct ListNode* next = NULL;struct ListNode* prev = NULL;for (int i = m; i <= n; i++) {next = cur->next;cur->next = prev;prev = cur;cur = next;}// 重新连接链表pre->next->next = cur;  // 新尾节点连接后继pre->next = prev;       // 前驱连接新头节点return dummy.next;  // 返回真正的头节点
}

解释一下实现过程:演示链表为1->2->3->4->5->NULL,m=2,n=4

1.创建哑节点

问题:处理 m=1 的特殊情况

当要从头节点开始反转(m=1)时:

  • 反转后头节点会改变(原第n个节点成为新头)

  • 如果没有哑节点,需要特殊处理这种情况

2.找到第m-1位的节点,开始 反转

for (int i = 1; i < m; i++) {pre = pre->next;
}
dummy → 1 → 2 → 3 → 4 → 5 → NULL↑pre (指向节点1)

3.连接反转后的链表与未反转的链表

未进行连接时(仅反转)

dummy → 1 → 2 ← 3 ← 4    5 → NULL↑          ↑    ↑pre        prev cur
反转部分:4 → 3 → 2 → NULL

进行连接后

dummy → 1 → 4 → 3 → 2 → 5 → NULL↑    ↑    ↑    ↑    ↑pre  新头  中间  新尾 cur

3.未使用哑节点的运行结果

我们将返回的哑节点改成head,就将会返回未使用哑节点的反转链表的头结点。

struct ListNode* reverseBetween(struct ListNode* head, int m, int n) {if (head == NULL || m == n) return head;// 创建哑节点 - 关键步骤!struct ListNode dummy;dummy.next = head;struct ListNode* pre = &dummy;// 移动到第 m-1 个节点for (int i = 1; i < m; i++) {pre = pre->next;}// 反转 m 到 n 的节点struct ListNode* cur = pre->next;struct ListNode* next = NULL;struct ListNode* prev = NULL;for (int i = m; i <= n; i++) {next = cur->next;cur->next = prev;prev = cur;cur = next;}// 重新连接链表pre->next->next = cur;  // 新尾节点连接后继pre->next = prev;       // 前驱连接新头节点return head;  // 返回
}

使用哑节点

这段代码可以直接运行检测结果

#include <stdio.h>
#include <stdlib.h>// 链表节点定义
struct ListNode {int val;struct ListNode* next;
};
// 创建新节点
struct ListNode* createNode(int value) {struct ListNode* newNode = (struct ListNode*)malloc(sizeof(struct ListNode));if (newNode == NULL) {printf("内存分配失败!\n");exit(1);}newNode->val = value;newNode->next = NULL;return newNode;
}
// 从数组创建链表
struct ListNode* createListFromArray(int arr[], int size) {if (size == 0) return NULL;struct ListNode* head = createNode(arr[0]);struct ListNode* current = head;for (int i = 1; i < size; i++) {current->next = createNode(arr[i]);current = current->next;}return head;
}// 交互式输入创建链表
struct ListNode* createListInteractive() {int n, value;printf("请输入链表节点个数: ");scanf("%d", &n);if (n <= 0) return NULL;printf("请输入%d个节点的值:\n", n);scanf("%d", &value);struct ListNode* head = createNode(value);struct ListNode* current = head;for (int i = 1; i < n; i++) {scanf("%d", &value);current->next = createNode(value);current = current->next;}return head;
}
// 打印链表
void printList(struct ListNode* head) {struct ListNode* current = head;printf("链表: ");while (current != NULL) {printf("%d", current->val);if (current->next != NULL) {printf(" → ");}current = current->next;}printf(" → NULL\n");
}// 带详细信息的打印
void printListDetailed(struct ListNode* head) {struct ListNode* current = head;int count = 1;printf("链表详细信息:\n");printf("地址       值   下一个节点\n");printf("-------------------------\n");while (current != NULL) {printf("%p  %2d  ", (void*)current, current->val);if (current->next != NULL) {printf("%p", (void*)current->next);} else {printf("NULL");}printf("\n");current = current->next;count++;}printf("-------------------------\n");
}
struct ListNode* reverseBetween(struct ListNode* head, int m, int n) {if (head == NULL || m == n) return head;// 创建哑节点 - 关键步骤!struct ListNode dummy;dummy.next = head;struct ListNode* pre = &dummy;// 移动到第 m-1 个节点for (int i = 1; i < m; i++) {pre = pre->next;}// 反转 m 到 n 的节点struct ListNode* cur = pre->next;struct ListNode* next = NULL;struct ListNode* prev = NULL;for (int i = m; i <= n; i++) {next = cur->next;cur->next = prev;prev = cur;cur = next;}// 重新连接链表pre->next->next = cur;  // 新尾节点连接后继pre->next = prev;       // 前驱连接新头节点return dummy.next;  // 返回真正的头节点
}
// 释放链表内存
void freeList(struct ListNode* head) {struct ListNode* current = head;while (current != NULL) {struct ListNode* temp = current;current = current->next;free(temp);}
}int main() {// 方法1: 从数组创建链表int arr[] = {1, 2, 3, 4, 5};int size = sizeof(arr) / sizeof(arr[0]);struct ListNode* head = createListFromArray(arr, size);printf("从数组创建的链表:\n");printList(head);printListDetailed(head);// 方法2: 交互式输入创建链表/*struct ListNode* head2 = createListInteractive();printf("交互式输入的链表:\n");printList(head2);freeList(head2);*/// 测试区间反转int m = 1, n = 4;printf("\n反转区间 [%d, %d] 后的链表:\n", m, n);// 这里可以调用你的reverseBetween函数head = reverseBetween(head, m, n);printList(head);// 释放内存freeList(head);return 0;
}

运行结果

~/gpt-vue_191657 gcc linkedlist.c -o linkedlist && ./linkedlist
从数组创建的链表:
链表: 1 → 2 → 3 → 4 → 5 → NULL
链表详细信息:
地址       值   下一个节点
-------------------------
0x557bae1cc2a0   1  0x557bae1cc2c0
0x557bae1cc2c0   2  0x557bae1cc2e0
0x557bae1cc2e0   3  0x557bae1cc300
0x557bae1cc300   4  0x557bae1cc320
0x557bae1cc320   5  NULL
-------------------------反转区间 [1, 4] 后的链表:
链表: 4 → 3 → 2 → 1 → 5 → NULL

反转函数返回值换为head后,运行结果:

~/gpt-vue_191657 gcc linkedlist_modified.c -o linkedlist_modified && ./linkedlist_modified
从数组创建的链表:
链表: 1 → 2 → 3 → 4 → 5 → NULL
链表详细信息:
地址       值   下一个节点
-------------------------
0x560fb96ca2a0   1  0x560fb96ca2c0
0x560fb96ca2c0   2  0x560fb96ca2e0
0x560fb96ca2e0   3  0x560fb96ca300
0x560fb96ca300   4  0x560fb96ca320
0x560fb96ca320   5  NULL
-------------------------反转区间 [1, 4] 后的链表:
链表: 1 → 5 → NULL

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/920058.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/920058.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

设计一个完整可用的 Spring Boot Starter

目录 1. 创建项目结构 2. 添加核心依赖 (pom.xml) 3. 实现核心组件 (1) 配置属性类 (2) 服务实现类 (3) 自动配置类 4. 注册自动配置 5. 配置元数据支持 6. 打包发布 7. 其他项目引用 (1) 添加依赖 (2) 配置参数 (3) 使用服务 设计要点 要设计一个完整可用的 Spr…

Bright Data 代理 + MCP :解决 Google 搜索反爬的完整方案

个人主页&#xff1a;chian-ocean 专栏 引言 人工智能技术和大数据的发展&#xff0c;实时访问网页数据成为许多应用的核心需求。相比传统方案依赖静态或定期更新的数据&#xff0c;AI可以实时抓取和分析网页上的及时更新的信息&#xff0c;迅速适应变化的环境&#xff0c;提…

Java基础第4天总结(多态)

package com.itheima.duotai;public class Animal {String name "动物";public void run(){System.out.println("动物会跑~~~");} }package com.itheima.duotai;public class Wolf extends Animal{String nama "狼";Overridepublic void run(…

Git克隆时遇到“Filename too long“错误的完美解决方案

Git克隆时遇到"Filename too long"错误的完美解决方案 问题描述 在使用Git克隆项目时&#xff0c;你是否遇到过这样的错误&#xff1a; $ git clone gitexample.com:project.git Cloning into project... remote: Enumerating objects: 1883, done. remote: Count…

分享一个基于Python与spark大数据的护肤品市场用户行为分析与可视化平台,基于hadoop的护肤品使用行为追踪与分析可视化平台的设计与实现

&#x1f495;&#x1f495;作者&#xff1a;计算机源码社 &#x1f495;&#x1f495;个人简介&#xff1a;本人八年开发经验&#xff0c;擅长Java、Python、PHP、.NET、Node.js、Spark、hadoop、Android、微信小程序、爬虫、大数据、机器学习等&#xff0c;大家有这一块的问题…

页面中嵌入Coze的Chat SDK

Coze 为将 AI 聊天机器人(Bot)嵌入您的网页提供了两种主流方式:Web SDK 和 API 接口调用。它们分别适用于不同的场景,下面我将为您介绍这两种方法,并提供一些选择建议。 特性 Web SDK API 接口调用 实现方式 引入一段JS代码,快速嵌入一个预制的聊天窗口 通过HTTP API发送…

DataEase+MaxKB:让BI再多个“A”

一、前言当前DataEase BI更多聚焦于BI展示层&#xff0c;然而&#xff0c;在与组件Copilot 以及后续计划替换的 Sqlbot的融合方面&#xff0c;目前仍存在一些亟待解决的问题&#xff0c;当它们尝试与 DataEase 进行结合应用时&#xff0c;出现了两种较为突出的状况。一方面&…

VUE 的弹出框实现图片预览和视频预览

这是一个基于Vue3封装的媒体预览组件&#xff0c;主要功能包括&#xff1a;多格式支持&#xff1a;可同时预览图片和视频图片操作功能&#xff1a;缩放&#xff08;支持滚轮缩放和按钮控制&#xff09;旋转&#xff08;90度增量旋转&#xff09;拖拽&#xff08;仅在放大状态下…

【Linux基础知识系列】第一百零九篇 - 使用shell的输入与输出重定向

在 Linux 系统中&#xff0c;Shell 是用户与操作系统交互的界面&#xff0c;通过命令行输入命令来执行各种操作。输入与输出重定向是 Shell 编程中非常重要的概念&#xff0c;它允许用户将命令的输出保存到文件中&#xff0c;或者从文件中读取输入&#xff0c;从而实现更灵活的…

Redis面试精讲 Day 30:Redis面试真题解析与答题技巧

【Redis面试精讲 Day 30】Redis面试真题解析与答题技巧 在“Redis面试精讲”系列的第30天&#xff0c;我们迎来收官之作——Redis面试真题解析与答题技巧。这一天的核心目标是&#xff1a;帮助你系统化梳理前29天所学知识&#xff0c;掌握高频面试题的解题思路&#xff0c;提升…

设计模式:单例模式(Singleton Pattern)

文章目录一、单例模式的概念二、单例模式的结构三、常见实现方式3.1 饿汉式单例3.2 懒汉式单例一、单例模式的概念 单例模式&#xff08;Singleton Pattern&#xff09;是一种创建型设计模式&#xff0c;它的核心思想是&#xff1a;保证在一个进程中&#xff0c;某个类仅有一个…

Swift 解法详解 LeetCode 362:敲击计数器,让数据统计更高效

文章目录 摘要 描述 题解答案 题解代码分析 代码讲解 示例测试及结果 时间复杂度 空间复杂度 总结 摘要 “敲击计数器”这道题听上去像个小游戏里的功能,但其实它背后对应的是一个常见的需求:在过去一段时间内统计事件发生的次数。比如网站的访问量统计、API 调用次数限制、…

coze工作流200+源码,涵盖AI文案生成、图像处理、视频生成、自动化脚本等多个领域

AI 博主风哥在github分享了 200 实用生产力coze工作流&#xff0c;涵盖AI文案生成、图像处理、视频生成、自动化脚本等多个领域&#xff0c;导入即用&#xff0c;项目地址https://github.com/Hammer1/cozeworkflows github下载慢也可前往该地址下载https://pan.baidu.com/s/1fC…

AI与SEO关键词协同优化

内容概要 人工智能&#xff08;AI&#xff09;技术的迅猛发展正深刻变革着搜索引擎优化&#xff08;SEO&#xff09;的实践方式&#xff0c;特别是在关键词策略这一核心领域。两者的深度融合&#xff0c;为企业在数字海洋中精准导航提供了前所未有的强大工具。通过AI驱动的智能…

【Unity开发】Unity核心学习(二)

二、动画基础 1、Animation动画窗口 &#xff08;1&#xff09;介绍&#xff08;2&#xff09;Animation窗口功能2、创建编辑动画 面板变化&#xff1a;动画文件界面&#xff1a;3、Animator动画状态机 &#xff08;1&#xff09;有限状态机概念&#xff08;2&#xff09;Anima…

NETSDK1045 当前 .NET SDK 不支持将 .NET 8.0 设置为目标。请将 .NET 5.0 或更低版本设置为目标,或使用支持

C# 项目中的目标框架无法修改并且显示为空 严重性 代码 说明 项目 文件 行 禁止显示状态 错误 NETSDK1045 当前 .NET SDK 不支持将 .NET 8.0 设置为目标。请将 .NET 5.0 或更低版本设置为目标&#xff0c;或使用支持 .NET 8.0 的 .NET SDK 版本。 Padim C:\Program …

MNIST 数据集mnist.npz详解

MNIST 数据集是机器学习领域最著名的数据集之一&#xff0c;全称为"Modified National Institute of Standards and Technology"数据库。它包含了大量手写数字的图像&#xff0c;是入门机器学习和深度学习的经典数据集。1. MNIST 数据集概述 60,000 张训练图像 10,00…

深入理解HTTPS:从概念到实战优化

深入理解HTTPS&#xff1a;从概念到实战优化一&#xff1a;概述二&#xff1a;工作流程三&#xff1a;创建自签名证书四&#xff1a;案例1&#xff09;案例一&#xff1a;HTTPS 搭建2&#xff09;案例二&#xff1a;HTTP/2 搭建3&#xff09;案例三&#xff1a;HTTP 重定向 HTT…

MySQL数据备份与恢复全攻略

一、数据备份与恢复按照备份方式分类&#xff1a;物理备份&#xff0c;直接复制数据库的物理文件&#xff0c;可以直接拷贝和恢复&#xff1b;逻辑备份&#xff0c;通过SQL语句导出数据库结构和数据&#xff0c;可用于不同版本和不同类型的MySQL数据库之间的数据迁移。按照数据…

单机多卡间大张量传输迷惑行为?

老铁们我最近真的好惨&#x1f62d;&#xff0c;一个大模型在单机多卡上运行就是出错&#xff0c;debug看的老眼昏花&#xff0c;最后发现大张量在设备间直接传输会有很发癫的行为&#xff0c;还请大家帮我看看&#x1f647;‍摒弃屎山一样的代码&#xff0c;简单运行下列脚本i…