首页 > 其他分享 >【模板】如何实现链表元素的反转

【模板】如何实现链表元素的反转

时间:2024-11-11 10:17:45浏览次数:3  
标签:Node node 反转 next 链表 节点 模板

反转链表是链表操作中一个经典的问题,也是面试中常见的考题。本文将从思路到实现一步步地讲解如何实现链表的反转,帮助初学者理解这一操作。我们将使用C++代码演示具体实现,同时分析时间复杂度和空间复杂度。

问题定义

给定一个单链表,我们需要将链表的节点顺序反转。例如,链表 1 -> 2 -> -2 -> 3 经过反转后变为 3 -> -2 -> 2 -> 1

思路分析

反转链表的核心在于修改每个节点的 next 指针,使其指向前一个节点。我们可以通过遍历链表,并逐个调整指针来实现链表的反转。这个过程的基本思路如下:

  1. 先定义一个指针 cur 用于跟踪当前处理的节点,并将它初始化为 nullptr
  2. 遍历链表中的每个节点,将当前节点的 next 指针调整为指向 cur
  3. 更新 cur 和遍历指针,直到遍历完成。
  4. 返回新的链表头,即原链表的尾节点。

这个过程可以在不使用额外存储空间的情况下完成链表的反转,因此其空间复杂度较低。

代码实现

以下是使用C++实现链表反转的代码:

#include "bits/stdc++.h"

using namespace std;

struct Node{
    int value;
    Node* next;
};

// 反转链表的函数
Node* reverseList(Node* node) {
    Node* cur = nullptr, *newNode = nullptr;
    while(node != nullptr) {
        newNode = node;            // 保存当前节点
        node = node->next;         // 移动到下一个节点
        newNode->next = cur;       // 将当前节点的next指向前一个节点
        cur = newNode;             // 更新cur为当前节点
    }
    return cur;                    // 返回新的头节点
}

int main() {
    // 创建一个示例链表:1 -> 2 -> -2 -> 3
    Node* head = new Node{1, new Node{2, new Node{-2, new Node{3, nullptr}}}};
    
    // 打印链表反转前的值
    Node* cur = head;
    while(cur != nullptr) {
        cout << cur->value << " "; 
        cur = cur->next;
    }
    cout << endl;
    
    // 反转链表
    cur = reverseList(head);
    
    // 打印链表反转后的值
    while(cur != nullptr) {
        cout << cur->value << " "; 
        cur = cur->next;
    }
    cout << endl;
}

带头节点的链表

若链表带头节点,可使用以下方式反转链表,此时头节点不会跟随链表的反转而变化。

Node* reverseNode(Node* head) {
	Node* curNode = nullptr, *node = head -> next;
	while(node) {
		Node* temp = node;
		node = node -> next;
		temp -> next = curNode;
		curNode = temp;
	}
	head -> next = curNode;
	return ; 
}

代码讲解

  • struct Node 定义了链表节点结构体,其中 value 存储节点值,next 存储指向下一个节点的指针。
  • reverseList 函数用于反转链表。在此函数中,我们使用两个指针:cur 记录已反转部分链表的尾节点,node 遍历链表并依次调整指针。
  • main 函数中创建一个简单链表,并分别在反转前后打印链表节点的值。

其他实现方式

递归反转链表

除了迭代法,我们还可以用递归的方式反转链表。递归法的思路是从链表末尾开始,将每个节点的 next 指针调整为其前一个节点,直到回到链表头节点。这种方法的代码实现如下:

Node* reverseListRecursive(Node* node, Node* prev = nullptr) {
    if (node == nullptr) return prev;    // 终止条件:到达链表末尾
    Node* next = node->next;             // 保存下一个节点
    node->next = prev;                   // 将当前节点的next指向前一个节点
    return reverseListRecursive(next, node);  // 递归处理下一个节点
}
比较两种方法
  • 迭代法:简单直接,时间复杂度为 O ( n ) O(n) O(n),空间复杂度为 O ( 1 ) O(1) O(1)。
  • 递归法:实现上更简洁,但由于递归调用栈的存在,其空间复杂度为 O ( n ) O(n) O(n),适用于链表长度较小的情况。递归深度过大会导致栈溢出问题。

时间和空间复杂度分析

对于上述代码,反转链表的时间复杂度和空间复杂度分别为:

  • 时间复杂度: O ( n ) O(n) O(n),其中 n n n 为链表节点数量。我们需要遍历链表中的每个节点,因此时间复杂度为 O ( n ) O(n) O(n)。
  • 空间复杂度: O ( 1 ) O(1) O(1),我们只使用了几个辅助指针来存储节点,没有额外占用大量空间。

总结

反转链表是链表操作中的基础知识,通过调整每个节点的指针可以实现高效的反转操作。本文介绍了迭代法和递归法两种反转链表的方式,并分析了各自的优缺点及复杂度,希望能对你有所帮助。

标签:Node,node,反转,next,链表,节点,模板
From: https://blog.csdn.net/qq_37945670/article/details/143600390

相关文章

  • 【模板】可持久化线段树 2(洛谷P3834)
    #include<bits/stdc++.h>#defineendl'\n'usingll=longlong;typedefunsignedlonglongull;usingnamespacestd;voidGordenGhost();constexprintN=2e5+7;intn,m,a[N],b[N];introot[N],tot;//根节点所有节点个数intls[N*40],rs[N*40],sum......
  • STM32+TMC2209控制步进电机正反转
    TMC2209是一款由Trinamic公司生产的高性能步进电机驱动器芯片,它支持SPI通信接口,能够实现精准的步进电机控制。本文将详细介绍如何使用STM32微控制器结合TMC2209驱动器来控制步进电机的正反转。TMC2209特点高精度控制:支持步进角为0.9°、1.8°、3.6°等多种细分设置。SPI接......
  • ROS2_机器人节点模板01_(万字?)_基于动作的实现
    事先声明在typora上做笔记时曾发生过数据丢失的问题,同时在转传到csdn上的时候也有轻微的问题,图片以及mermaid图。如果看的不够清晰可以留言,我将视情况提供原版markdown文件。一些建议请在阅读这份笔记时充分利用目录本笔记包含非常多拓展内容和衍生知识,你可以先阅读重......
  • 单调栈基础模板
    #include<bits/stdc++.h>usingnamespacestd;constintN=1000005;intn,ansl[N],ansr[N],a[N];intf[N],r,x;intmain(){cin>>n;for(inti=0;i<n;i++)cin>>a[i],ansl[i]=ansr[i]=-1;for(inti=0;i<n;i++){......
  • MDPI之Applied Science word 模板下载
    因为之前找过很多资料,都没有word模板下载的教程,所以在这里留个记号。官网点此一、进入如下页面 二、下拉找到Submissionchecklist在这里有 MicrosoftWord模板和 LaTeX模板(在此处单击或去官网点击即可自行下载)。......
  • C/C++语言基础--C++模板与元编程系列五(可变惨模板,形参包展开,折叠表达式)
    本专栏目的更新C/C++的基础语法,包括C++的一些新特性前言模板与元编程是C++的重要特点,也是难点,本人预计将会更新10期左右进行讲解,这是第五期,讲解可变惨模板,形参包展开,折叠表达式等,本人感觉这一部分内容还是比较复杂的;C语言后面也会继续更新知识点,如内联汇编;欢迎收藏+关......
  • C++之模板
    C++模板是一种支持泛型编程的机制,允许开发者定义使用任意类型作为参数的函数和类。模板提供了代码复用和类型安全的抽象,使得同一段代码可以用于不同的数据类型。函数模板定义和使用函数模板是一种可以接受任意类型参数的函数。它通过在函数声明中使用模板参数(用尖括号<>包围......
  • 【java】通过<类与对象> 引入-> 链表
    目录链表碎片化:内存碎片产生的原因如何避免内存碎片?链表类型单链表双链表单循环链表双循环链表java是如何创建链表的?类与对象类是什么?什么是对象?构建链表头指针简画内存图: ​编辑尾插法 头插法输出链表的长度输出链表的值链表为什么会有链表?  ......
  • 将给定的表达式树(二叉链表存储)转换为等价的中缀表达式(递归)
    3765.表达式树可以拿这题验证自己的代码对不对ps:这里不是这题的答案,参照代码思路写即可voidBtreeToe(Btree*root){ BtreeToExp(root,1);//根的高度为1 }voidBtreeToExp(Btree*root,intdep){ if(root==NULL)return;//如果是空结点返回 elseif(!root->lef......
  • CTF-WEB: python模板注入
    漏洞是如何产生的?Python模板注入漏洞通常出现在使用模板引擎生成动态内容的应用中。如果用户输入没有经过适当的处理直接插入模板中,就可能会导致模板注入漏洞。一个常见的例子是使用Jinja2模板引擎时,如果直接渲染用户输入,则可能导致代码执行等严重后果。以下是一个演示如......