博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
全面分析再动手的习惯:链表的反转问题(递归和非递归方式)
阅读量:6501 次
发布时间:2019-06-24

本文共 2288 字,大约阅读时间需要 7 分钟。

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

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

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

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

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

#include 
using namespace std;typedef struct Node{ int data; Node *next;} Node, *List;Node * reverseList(List head){ //定义三个指针,保存原来的连接的状态 //当前结点指针 Node *pnow = head; //当前结点的前驱指针,初始化是 NULL Node *pre = NULL; //当前结点的后继指针,初始化也是 null Node *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,也就是反转之后的链表,此时递归工作栈的函数全部执行,返回的结点就是反转之后的链表的头结点(之前的尾结点)

 

转载地址:http://jbvyo.baihongyu.com/

你可能感兴趣的文章
恢复误删的进程在使用的文件【转】
查看>>
android休眠唤醒驱动流程分析【转】
查看>>
Tslib移植与分析【转】
查看>>
WIN7 任务栏放右侧 有个BUG
查看>>
结对项目进展
查看>>
创建服务
查看>>
Dispatcher与UI线程交互
查看>>
如何实现网站的防盗链?
查看>>
css控制非固定文本自动换行
查看>>
区块链基本解读
查看>>
小鱼提问1 类中嵌套public修饰的枚举,外部访问的时候却只能Class.Enum这样访问,这是为何?...
查看>>
wps 2016 个人版 重新开始编号
查看>>
求二维数组中最大子数组的和
查看>>
你不知道的对称密钥与非对称密钥
查看>>
替换IMG
查看>>
面向对象
查看>>
深入理解 python 元类
查看>>
最常用的Linux命令
查看>>
MVC+Ninject+三层架构+代码生成 -- 总结(四、數據層)
查看>>
python之XML文件解析
查看>>