定义一个方法(函数),实现输入一个链表的头结点,然后可以反转这个链表的方向,并输出反转之后的链表的头结点。

typedef struct Node{int data;Node *next;
} Node, *List;

链表类的问题,涉及到了很多指针的操作,需要严谨的分析,全面的分析问题之后,在开始写代码,磨刀不误砍柴工!反转链表,直接的想法,就是把链表中指针的方向反转就可以了,如图所示:

假设 i 结点之前,我们把所有的结点的指针都已经反转了,那么自然 i 和以后的结点链接发生了断裂!如下图;

这样的话,无法继续遍历 i 以后的结点了,那么自然想到,在断链之前,提前保存之前的状态。那么自然想到定义三个指针,分别指向当前结点 i,i 的后继 j,i 的前驱 h 结点。保存断链之前的三个结点的连接状态。然后,假设没问题了,那么继续反转完毕,最后链表的尾结点就是反正链表的头结点了,也就是 next 为 null 的结点,是原始链表的尾结点。

#include <iostream>
using namespace std;typedef struct Node{int data;Node *next;
} Node, *List;Node * reverseList(List head){//定义三个指针,保存原来的连接的状态//当前结点指针Node *pnow = head;//当前结点的前驱指针,初始化是 NULLNode *pre = NULL;//当前结点的后继指针,初始化也是 nullNode *pnext = NULL;//定义尾指针Node *tail = NULL;//开始遍历链表while(pnow != NULL){//如果当前结点不是 null,那么初始化 pnext 指针指向当前结点的下一个结点pnext = pnow->next;//如果找到了尾结点,初始化 tail 指针if(NULL == pnext){tail = pnow;}//进行链表的反转,当前结点的 next 指针指向前一个结点,实现链表方向的反转,此时发生了断链pnow->next = pre;//勿忘断链的情形,需要使用 pre 指针保存状态,pre 等价于是后移一个结点pre = pnow;//pnow 后移一个结点pnow = pnext;}return tail;
}

定义的这个三个指针,目的就是防止断链之后无法继续遍历链表以后的结点,实现全部的反转。当 pnow 的 next 指向 pnow 的前驱pre(初始化是 null)的时候,已经实现了 pnow 和前驱pre的方向反转,但是 pnow 此时就和后继pnext断链了,那么使用 pre 后移的方式,指向 pnow,同时 pnow 也后移,指向 pnext,而 pnext 继续指向更新之后的 pnow 的 next 结点即可。从而实现了状态的保存,继续遍历全部结点,实现链表反转。

注意关于链表问题的常见注意点的思考:

1、如果输入的头结点是 NULL,或者整个链表只有一个结点的时候

2、链表断裂的考虑

下面看看递归的实现方式

递归的方法其实是非常巧的,它利用递归走到链表的末端,然后再更新每一个node的next 值 ,实现链表的反转。而newhead 的值没有发生改变,为该链表的最后一个结点,所以,反转后,我们可以得到新链表的head。

//递归方式
Node * reverseList(List head)
{//如果链表为空或者链表中只有一个元素if(head == NULL || head->next == NULL){return head;}else{//先反转后面的链表,走到链表的末端结点Node *newhead = reverseList(head->next);//再将当前节点设置为后面节点的后续节点head->next->next = head;head->next = NULL;return newhead;}
}

程序刚开始执行,if 语句失效,进入 else 语句,然后执行Node *newhead = reverseList(head->next);第二个结点的指针参数传入递归函数,一直到,最后一个结点的指针参数传入递归函数,if 语句有效head->next == NULL,返回当前的head 给 newhead 指针指向,如图:

其实在递归函数栈内,按照后进先出的顺序,执行一级级的递归函数,返回末位结点给 newhead 之后,执行递归栈里的第二个递归函数,发生如图

返回 newhead,也就是新的反转之后的链表(临时的),然后进入到递归工作栈里的第一个递归函数,如图:

返回 newhead,也就是反转之后的链表,此时递归工作栈的函数全部执行,返回的结点就是反转之后的链表的头结点(之前的尾结点)

全面分析再动手的习惯:链表的反转问题(递归和非递归方式)相关推荐

  1. 单链表反转(递归和非递归)

    单链表反转有递归和非递归两种算法. 下面定义节点 [cpp] view plaincopy typedef struct ListNode{ int value; ListNode* next; }L ...

  2. 逆置单链表——递归与非递归

    文章目录 前言 方式一:非递归 原理 图解 实现代码 方式二:递归 原理 图解 实现代码 完整实现 代码 运行结果 前言 单链表的逆置图解 方式一:非递归 原理 非递归逆置单链表的本质是创建一个新的链 ...

  3. 合并两个排序的链表递归和非递归C++实现

    题目描述: 输入两个单调递增的链表,输出两个链表合成后的链表,要求合成后的链表满足单调不减规则. 1.分析 已知输入的两个链表递增有序,要使输出的链表依然递增有序,可以依次从输入的两个链表中挑选最小的 ...

  4. C++递归与非递归实现链表的反转

    思想参考:http://ceeji.net/blog/reserve-linked-list-cpp/ #include"list.h" using namespace std; ...

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

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

  6. 链表反转两种方式(递归和非递归)

    非递归: 思想:设置pre 和 cur 两个链表:pre用来存储已经反转过的链表,cur存储当前未反转的链表 每一次将 cur 的当前节点的next引用将未反转链表转向反转链表,并将当前节点移动到pr ...

  7. 快速排序算法思路分析和C++源代码(递归和非递归)

    快速排序由于排序效率在同为O(N*logN)的几种排序方法中效率较高,因此经常被采用,再加上快速排序思想----分治法也确实实用,因此很多软件公司的笔试面试喜欢考这个. 快速排序是C.R.A.Hoar ...

  8. java 链表逆序 递归,java用递归和非递归实现链表逆序

    传统的逆序链表方法是使用三个指针来记录节点的状态,防止链表断裂. Node节点 public class Node { private int data; private Node next; pub ...

  9. 斐波那契数与二分法的递归与非递归算法及其复杂度分析

    1. 什么是斐波那契数? 这里我借用百度百科上的解释:斐波那契数,亦称之为斐波那契数列(意大利语: Successione di Fibonacci),又称黄金分割数列.费波那西数列.费波拿契数.费氏 ...

最新文章

  1. chrdev字符设备几种注册方式的差异
  2. 石锤!谷歌排名第一的编程语言,死磕这点,程序员都收益
  3. 利用nginx泛域名解析配置二级域名和多域名
  4. ps -ef和ps aux的区别
  5. python中字符串相关
  6. 【C语言】时间操作,把1970年开始秒数计算的时间,转换为字符串格式输出
  7. CentOS下安装网卡驱动
  8. 如何在eclipse中装myeclipse的插件
  9. MSSQL-最佳实践-Always Encrypted
  10. python 5的倍数_查找所有低于1000的数字的和,这是Python中3或5的倍数
  11. 【BZOJ4247】挂饰,又一个奇特的背包
  12. c语言将数组元素循环右移3位,如何将一个数组的元素循环左移?
  13. zillow房价预测比赛_Zillow Prize: 百万美刀奖金的房价预测比赛
  14. php在线加密lua,AES 256 Lua + PHP
  15. 安全基础-防火墙四种登录方式 SSH Telnet SSH
  16. 读论文:大数据计算环境下的隐私保护技术研究进展
  17. 【FPGA——工具篇】32个FPGA开源网站
  18. 10个 Istio 流量管理 最常用的例子,你知道几个?
  19. 小何的第一篇博客+GitHub的基本设置
  20. 【飞桨】Seg:U-Net【2015 MICCAI】论文研读

热门文章

  1. SpringBoot conditional注解和自定义conditional注解使用
  2. ATT与Intel汇编语言的比较
  3. C#的6种常用集合类大比拼【月儿原创】
  4. size_t与ssize_t
  5. C和C++安全编码笔记:总结
  6. Python实现决策树(Decision Tree)分类
  7. C/C++中inline/static inline/extern inline的区别及使用
  8. 设计模式之组合模式(Composite)摘录
  9. 【FFmpeg】结构体详解(一):AVCodec、AVCodecContext、AVCodecParserContext、AVFrame、AVFormatContext 、AVIOContext
  10. python字符串常量_python教程---字符串常量ascii_letters、punctuation、digits、whitespace等...