这道题是一道经典的算法题了,出没在各大厂小厂的面试题中,也出现在了我去年的考研题中,当时写的很烂,残念。。
从考研题说起,当时题目的要求还比较严苛,要求不能借助额外的辅助空间,也就是要求完全通过操作指针来实现链表的逆转,查阅了一些资料,发现此题主要有两种解法——迭代法和递归法。
(1)迭代法
迭代法用经典的“双指针法”遍历整个链表,其中cur指向当前结点,pre指向cur结点的前驱结点,同时用一个缓存tmp指向cur的后继结点,当cur不为空时,一直迭代执行以下操作:
tmp = cur -> next
cur -> next = pre
pre = cur
cur = tmp
遍历完成后,pre即指向新链表的头结点,而将原本头结点的指针域置为NULL即可。
C语言实现(这里仅给出结点类型和reverse函数):
接口:LinkNode *reverse(LinkNode *head);
输入:原链表的头结点
返回:逆转后链表的头结点
typedef struct LinkNode
{
int data; //假设值域为整型,无关紧要,甚至不要值域也行
LinkNode *next;
}LinkNode;
LinkNode *reverse(LinkNode *head)
{
LinkNode *pre = head;
LinkNode *cur = head->next;
LinkNode *tmp = NULL;
while(cur)
{
tmp = cur->next;
cur->next = pre;
pre = cur;
cur = tmp;
}
head->next = NULL;
return pre;
}
(2)递归法
用递归法逆转链表的思路则更为直接:若传入的结点有后继结点,则先对后继结点进行逆转操作,直至追溯至链表的尾结点,进行逆转操作,将当前结点的后继结点的后继指向自己,并将当前结点的指针域置为NULL即可。
C语言实现:
typedef struct LinkNode
{
int data; //假设值域为整型,无关紧要,甚至不要值域也行
LinkNode *next;
}LinkNode;
LinkNode *reverse(LinkNode *head)
{
if(head == NULL||head->next == NULL)
return head; //若递归到尾结点,则开始回溯
LinkNode *rehead = reverse(head->next);
head->next->next = head;
head->next = NULL;
return rehead;
}