链表翻转的图文讲解(递归与迭代两种实现)

转载

链表翻转的图文讲解(递归与迭代两种实现)

链表的翻转是程序员面试中出现频度最高的问题之一,常见的解决方法分为递归和迭代两种。最近在复习的时候,发现网上的资料都只告诉了怎么做,但是根本没有好好介绍两种方法的实现过程与原理。所以我觉得有必要好好的整理一篇博文,来帮忙大家一步步理解其中的实现细节。 

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

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、整体实现的程序: 

#includeusing 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;

}

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容

  • 转载自http://blog.csdn.net/fx677588/article/details/72357389...
    杰伦哎呦哎呦阅读 1,118评论 0 0
  • 1.HashMap是一个数组+链表/红黑树的结构,数组的下标在HashMap中称为Bucket值,每个数组项对应的...
    谁在烽烟彼岸阅读 1,009评论 2 2
  • 搞懂单链表常见面试题 Hello 继上次的 搞懂基本排序算法,这个一星期,我总结了,我所学习和思考的单链表基础知识...
    醒着的码者阅读 4,572评论 1 45
  • 今天一个人跑医院看牙。 重新装修过的医院太高大上以至于差点找不到地方。感谢热心的护士。 等了一个小时,终于轮到我了...
    13267734d82e阅读 194评论 1 1
  • HTTP请求的常见方法 GET所有参数拼接在URL后面,并且参数之间用&隔开比如http://520it.com?...
    蠢萌的L君阅读 451评论 0 4