链表翻转常见的方法分为递归和迭代两种。

我们知道迭代是从前往后依次处理,直到循环到链尾;而递归恰恰相反,首先一直迭代到链尾也就是递归基判断的准则,然后再逐层返回处理到开头。总结来说,链表翻转操作的顺序对于迭代来说是从链头往链尾,而对于递归是从链尾往链头。下面我会用详细的图文来剖析其中实现的细节。
1、迭代方式
  迭代的方式是从链头开始处理,如下图给定一个存放5个数的链表。

  首先对于链表设置两个指针:

  然后依次将旧链表上每一项添加在新链表的后面,然后新链表的头指针NewH移向新的链表头,如下图所示。此处需要注意,不可以上来立即将上图中P->next直接指向NewH,这样存放2的地址就会被丢弃,后续链表保存的数据也随之无法访问。而是应该设置一个临时指针tmp,先暂时指向P->next指向的地址空间,保存原链表后续数据。然后再让P->next指向NewH,最后P=tmp就可以取回原链表的数据了,所有循环访问也可以继续展开下去。

  指针继续向后移动,直到P指针指向NULL停止迭代。

  最后一步:

2、迭代实现的程序

node* reverseList(node* H)
{if (H == NULL || H->next == NULL) //链表为空或者仅1个数直接返回return H;node* p = H, *newH = NULL;while (p != NULL)                 //一直迭代到链尾{node* tmp = p->next;          //暂存p下一个地址,防止变化指针指向后找不到后续的数p->next = newH;               //p->next指向前一个空间newH = p;                     //新链表的头移动到p,扩长一步链表p    = tmp;                   //p指向原始链表p指向的下一个空间}return newH;
}

3、递归方式
  我们再来看看递归实现链表翻转的实现,前面非递归方式是从前面数1开始往后依次处理,而递归方式则恰恰相反,它先循环找到最后面指向的数5,然后从5开始处理依次翻转整个链表。
  首先指针H迭代到底如下图所示,并且设置一个新的指针作为翻转后的链表的头。由于整个链表翻转之后的头就是最后一个数,所以整个过程NewH指针一直指向存放5的地址空间。

  然后H指针逐层返回的时候依次做下图的处理,将H指向的地址赋值给H->next->next指针,并且一定要记得让H->next =NULL,也就是断开现在指针的链接,否则新的链表形成了环,下一层H->next->next赋值的时候会覆盖后续的值。

  继续返回操作:

  上图第一次如果没有将存放4空间的next指针赋值指向NULL,第二次H->next->next=H,就会将存放5的地址空间覆盖为3,这样链表一切都大乱了。接着逐层返回下去,直到对存放1的地址空间处理。

  返回到头:

4、递归实现的程序

node* In_reverseList(node* H)
{if (H == NULL || H->next == NULL)       //链表为空直接返回,而H->next为空是递归基return H;node* newHead = In_reverseList(H->next); //一直循环到链尾 H->next->next = H;                       //翻转链表的指向H->next = NULL;                          //记得赋值NULL,防止链表错乱return newHead;                          //新链表头永远指向的是原链表的链尾
}

5、整体实现的程序:

#include<iostream>
using namespace std;struct node{int val;struct node* next;node(int x) :val(x){}
};
/***非递归方式***/
node* reverseList(node* H)
{if (H == NULL || H->next == NULL) //链表为空或者仅1个数直接返回return H;node* p = H, *newH = NULL;while (p != NULL)                 //一直迭代到链尾{node* tmp = p->next;          //暂存p下一个地址,防止变化指针指向后找不到后续的数p->next = newH;               //p->next指向前一个空间newH = p;                     //新链表的头移动到p,扩长一步链表p    = tmp;                   //p指向原始链表p指向的下一个空间}return newH;
}
/***递归方式***/
node* In_reverseList(node* H)
{if (H == NULL || H->next == NULL)       //链表为空直接返回,而H->next为空是递归基return H;node* newHead = In_reverseList(H->next); //一直循环到链尾 H->next->next = H;                       //翻转链表的指向H->next = NULL;                          //记得赋值NULL,防止链表错乱return newHead;                          //新链表头永远指向的是原链表的链尾
}
int main()
{node* first = new node(1);node* second = new node(2);node* third = new node(3);node* forth = new node(4);node* fifth = new node(5);first->next = second;second->next = third;third->next = forth;forth->next = fifth;fifth->next = NULL;//非递归实现node* H1 = first;H1 = reverseList(H1);    //翻转//递归实现node* H2 = H1;    //请在此设置断点查看H1变化,否则H2再翻转,H1已经发生变化H2 = In_reverseList(H2); //再翻转return 0;
}
  • 转载自:http://blog.csdn.net/FX677588/article/details/72357389

链表的翻转(迭代法 递归法)相关推荐

  1. c语言库快速幂函数,C语言 - 快速幂 - 迭代法+递归法 - 详细讲解

    快速幂的作用: 解决 求 a ^ n 的问题 (n可以大于1e18), 如果用for循环的话,毫无疑问直接炸掉 -- 所以也就用了算法复杂度在 o(log n)的快速幂算法来解决此类问题. 快速幂递归 ...

  2. 常考数据结构与算法:判断二叉树是否对称(迭代法,递归法)

    给定一棵二叉树,判断琪是否是自身的镜像(即:是否对称) 例如:下面这棵二叉树是对称的      1     /  \   2    2  / \    / \ 3 4  4  3 下面这棵二叉树不对称 ...

  3. 翻转链表python递归_Python实现链表反转的方法【迭代法与递归法】

    导读 这篇文章主要介绍了Python实现链表反转的方法,结合实例形式分析了Python迭代法与递归法实现链表反转的相关操作技巧与注意事项,需要的朋友可以参考下 本文实例讲述了Python实现链表反转的 ...

  4. 实现链表反转(迭代法,递归法)

    反转前: 反转后: 迭代法 实现思路: 迭代法实现链表反转的思路其实很简单,反转之前链表的节点的指针域指向的是下一个节点,反转之后我们只需要将当前节点的指针域指向前一个节点,由于是单链表,只能通过节点 ...

  5. python递归合并排序_python 归并排序的递归法与迭代法(利用队列)实现,以及性能测试...

    递归排序核心 递归排序的核心是 分与合 分的最终结果 就是将原数组中每一个数字分作一个数组, 合就是 所有小数组不断排序,合并的过程. 合并的过程是先将两个含有一个数字的数组排序,合并(每次比较两个数 ...

  6. java 链表反转 递归_递归法的理解——以反转链表为例

    2020-01-07 递归是什么: 递归,从定义上说,指的是某个函数直接或者间接调用自己时,则发生了递归. 比如说著名的斐波拉契数列的实现方法之一: 1 public static int f(int ...

  7. 翻转链表II[翻转链表3种方式+dummyHead/头插法/尾插法]

    翻转链表 前言 一.翻转链表中间部分 二.dummyHead&头插法&尾插法 1.一次扫描 + 翻转链表(另一次扫描) 2.一次扫描&头插法&尾插法(进阶) 总结 参考 ...

  8. 递归与非递归法实现链表相加 CC150 V5 2.5题 java版

    前言:这是一道很有意思的题目,原题如下: You have two numbers represented by a linked list, where each node contains a s ...

  9. 大厂面试算法系列-如何实现链表的逆序(二)-递归法

    导语   接着上次的内容,上次博客中展示了原地进行单链表的逆序操作,当然除了原地逆序还可以通过递归的方式进行调用操作.下面就来看看通过递归的方式如何进行单链表的逆序操作. 递归法逆序链表   假定原来 ...

最新文章

  1. Spark源码阅读02-Spark核心原理之消息通信原理
  2. vue路由切换组件没有加载_vue-router 路由跳转后没有加载组件
  3. jquery+bootstrap实现tab切换, 每次切换时都请求数据, 点击提交分别向不同的地址提交数据...
  4. Linux防火墙屏蔽ip6,观点|Linux 发行版们应该禁用 IPv4 映射的 IPv6 地址吗?
  5. ps专业色彩调色扩展面板 Moody Photoshop Panel 1.1.2汉化版
  6. java 模板方法_Java设计模式21:模板方法(Template Method)
  7. pandas 非聚合函数
  8. matlab 图像的膨胀indilate和腐蚀imerode
  9. docker上安装nginx服务
  10. 2.卷1(套接字联网API)---传输层:TCP,UDP 和 SCTP
  11. 带aidl文件的应用程序在android平台源码中的编译
  12. JavaWeb之HttpSession
  13. MicrosoftStore无法下载软件
  14. 全文标明引文报告html,知网查重报告之全文(标明引文)报告单参数详解
  15. Scratch模拟题(二级)_1
  16. WPF 控件【U】UserControl(一) UserControl、ContentControl、Page的区别,及它们的使用方法
  17. go语言里读写json
  18. OWASP TOP 10 漏洞指南(2021)
  19. amd同步多线程_流言终结者系列:第三代锐龙关同步多线程能增加游戏帧数?
  20. 如何在二维或三维地图中叠加一个视频(以mapboxgl为例)

热门文章

  1. MVC3.0与C#截取字符串
  2. Initramfs应用问题记录
  3. 蓝桥杯 ALGO-13 算法训练 拦截导弹 Java版
  4. linux tcp重传超时时间,tcp 重传超时次数
  5. python django 优势_为什么选择Django?
  6. python查找字符串数量_python如何实现从字符串中找出字符1的位置以及个数的示例...
  7. Perl_获得字符串长度_length($var)
  8. Python用format格式化字符串
  9. [strace]跟踪进程的系统调用
  10. Linux命令简写和全称-2