zoukankan      html  css  js  c++  java
  • 翻转链表-迭代和递归双版本

    将一个链表翻转,如 1->2->3->4 变成 4->3->2->1 的链表。这是一个非常著名的面试题,看似非常的简单,但实际上非常的tricky.

    实现方法可以有递归和迭代两种方法,这两个算法也都保证了in-place 和 one-pass. 所以效率还是很高的。这篇文章主要基于http://leetcode.com/2010/04/reversing-linked-list-iteratively-and.html. 他讲解的基本已经比较清楚,我就再从比较菜的角度去分析一下。

    迭代方法:

    首先来看迭代版本的基本思路,先上图:

    上图就是迭代的第一步,基本就是prev, curr, next三个指针跟踪着当前点的情况,然后更新后向前移动,直到移到链表末尾

    看代码后应该更清晰:

     1 void reverse(Node*& head) {
     2   if (!head) return;
     3   Node* prev = NULL;
     4   Node* curr = head;
     5   while (curr) {
     6     Node* next = curr->next;
     7     curr->next = prev;
     8     prev = curr;
     9     curr = next;
    10   }
    11   head = prev;
    12 }

    代码中要注意 Node*&, 毕竟是改变了链表的结构,所以链表的头指针应该传一个引用。

    翻转链表的迭代版本很清晰,且容易实现。而下面的递归方法虽然代码很短,但是比较难理解,且实现起来细节也很多。

    递归版本:

    这个整体过程比较复杂,所以还是先上图:

    然后来看着代码分析:

    void reverse(Node*& p) {
      if (!p) return;
      Node* rest = p->next;
      if (!rest) return;
      reverse(rest);
      p->next->next = p;
      p->next = NULL;
      p = rest;
    }

    递归过程中,首先迅速由递归函数进行至第一幅图的情况(其实下面还有一步,此时rest 指向NULL,返回到第一幅的情况)

    然后将当前节点的下一节点的子节点倒指向其父节点(即当前节点),然后将当前节点指向NULL,即当前我们翻转了从当前节点到末尾节点。

    注意这之后的最后一个语句,将p 赋值为 rest,然后返回。 返回到上一层会发生什么呢? 这就要注意每层调用reverse函数时,传进去的指针式rest, 即修改上一层的rest指针为当前层的rest指针,换句话说,在以后递归的过程中,rest指针将一直指向最后一个节点,即新的链表根节点。

  • 相关阅读:
    strcat strcpy 使用出现的问题汇总
    MySql Host is blocked because of many connection errors; unblock with 'mysqladmin flush-hosts' 解决方法
    nginx 设置反响代理实现nginx集群
    js 去掉字符串最后一个字符
    二维数组 获取某键值集合
    oracle 序列
    递归数据查询
    oracle 递归查询
    jQuery EasyUI API 中文文档
    SecureCRT使用的技巧 键盘修改
  • 原文地址:https://www.cnblogs.com/soyscut/p/3801539.html
Copyright © 2011-2022 走看看