单链表反转

  单链表反转是一个经典的面试题。

  单链表反转问题可以类比成一个倒叙的数列进行插入排序,实际上是将第二个开始的每个元素提取到链表的最前面。

  单链表数据结构定义:

  

1 struct ListNode {
2     int val;
3     ListNode *next;
4     ListNode(int x) : val(x), next(NULL) {}
5  };

  有三个问题需要注意:

  1.在将第二个元素开始的每个元素提取到链表最前面时,需要将第一个元素指向提取元素的后一个元素(否则循环无法进行)。

  2.修改提取元素指向链表头。

  3.具体逻辑。head指向未进行任何操作时的第一个节点,且在循环中一直指向这个节点;tail指向当前提取的节点,显然开始时tail=head->next;prev指向链表头,且一直指向的是链表头,很显然开始prev=head

  具体操作为:

  head->next=tail->next;      //将head指向提取节点的后一个节点

  tail->next=p;                     //将提取的节点插入到链表头

  p=tail;                               //修改链表头尾提取的节点

  tail=head->next;             //将tail指向下一个提取的节点

  此问题也可以使用递归方法进行实现

  用递归方法实现即为一直进行递归head=head->next找到最后一个节点

  然后从最后一个节点开始,重新建立链表的关系,实现的代码如下:

  

ListNode * ReverseList(ListNode * head)
{
    //递归终止条件:找到链表最后一个结点
    if (head == NULL || head->next == NULL)
        return head;
    else
    {
        ListNode * newhead = ReverseList(head->next);//先反转后面的链表,从最后面的两个结点开始反转,依次向前
        head->next->next = head;//将后一个链表结点指向前一个结点
        head->next = NULL;//将原链表中前一个结点指向后一个结点的指向关系断开
        return newhead;
    }
}

  同时实现单链表反转一个简易并且容易理解的方法是:使用栈,将每个节点的指针入栈(而不是节点本身),然后stack.pop()进行出栈指针,重新建立单链表的关系,只是这种方法需要消耗O(n)的空间,但是相对来说易于操作和理解。

  

原文地址:https://www.cnblogs.com/wangshi2019/p/10657763.html