MENU

链表|如何将一个链表逆序

February 13, 2019 • 我爱学习

  链表,我们都熟知的一种数据结构,今天来讲讲如何将一个链表的顺序倒过来。这是一道比较基础的面试题,但要一次写对还真的不太容易。

  首先,链表逆序的操作都是作用在单向列表之中的,这其中的原因就不必细说了。
  假定我们有一个链表 [3]->[5]->[1]->[4]->[9] ,链表逆序,其本质就是将每一个节点的next指针倒置过来,使原本指向下一个节点的next指针指向当前节点的上一个节点。具体目的示范如下图。

  首先,先从链表的某个节点来看,把它的next指针倒转,我们最少需要知道 3 个节点,分别是:某个节点本身,其前置节点,其后置节点。知道其前置节点,是为了next指针倒转时有节点可以指向;知道其后置节点,是为了当前节点的next完成倒转操作之后,链表逆向操作可以继续进行下去。

  那么接下来我们开始进行完整的链表逆向操作:首先先要建立三个临时的节点p1,p2,p3,分别指向头节点,第二个节点,第三个节点
  首先,以p2指向的节点为视角,将p2节点上next指向p1
  然后将p1,p2,p3都向后移一个节点,即p1指向第二个节点,p2指向第三个节点,p3指向第四个节点。继续执行第一步的操作。以此类推,直到p2的值为NULL的时候停止。
  最后将原本头节点的next指针指向为NULL。让当前p1所指向的节点为头节结点
  图片示例如下:

  1. 将p1,p2,p3分别指向头节点,第二个节点,第三个节点。

  2. 将p2节点上next指向p1

3. p1,p2,p3都向后移一个节点

4. 继续执行第一步的操作

5. 继续执行第二步的操作

6. 直到p2为空的时候停止

**7. 此时将原本的头节点指向为NULL
p1所指向的节点为头节结点**

那么代码是如何实现的呢?

static struct Node //定义节点结构体
{    
  int data;
  Node *next;
}
    
static struct Node head; //定义一个静态临时头节点

void reverseLinkedList() //定义一个函数,进行节点逆序的操作
{
  if(head==null || head.next==null) //判断头节点引导的链表是否存在或为单个节点
  {
    return; //判断为真,推出节点逆序函数
  }

  Node p1 = head;    
  Node p2 = head.next;    
  Node p3 = null; //定义临时节点p1,p2,p3

  while(p2 != null) //p2的值不为NULL的时候,
  {
        p3 = p2.next; //将临时节点p3指向p2的下一个节点
        p2.next = p1; //p2的next指针倒置
        p1 = p2;
        p2 = p3;    //p1,p2指针向后移一个节点
  }

  head.next = null;
    head = p1;
}

int main()
{
  struct Node node1,node2,node3,node4,node5;
  node1->data = 3;
  node2->data = 5;
  node3->data = 1;
  node4->data = 4;
  node5->data = 9;
  node1->next = node2;
  node2->next = node3;
  node3->next = node4;
  node4->next = node5;
  head->next = node1;
  //初始化链表

  reverseLinkedList(); //逆序链表

  //输出结果
  struct temp = head;
  while(temp != NULL)
  {
    printf("%d",temp->data);
    temp = temp.next;
  }
}

  链表反转的逻辑本身,都在reverseLinkedList函数当中。在这里我们把链表的头节点作为了静态变量,实际上也可以作为参数传入,只是逻辑上需要一些小小的修改。

Last Modified: September 8, 2021