思路1:取原链表的节点,依次头插到新链表,返回新链表的头
示例一反转步骤如下:
📖Note:
- 当cur != NULL时,将cur指向的节点头插入新链表,首先要更改cur->next的值为newhead->next,再更改newhead的值为cur,两者顺序不能调换
- 更改cur->next后就不能找到原链表中cur的下一个节点,所以我们要定义一个变量存储cur->next的值
参考代码如下:
struct ListNode* reverseList(struct ListNode* head){
struct ListNode* cur = head;
struct ListNode* newhead = NULL;
while(cur)
{
struct ListNode* next= cur->next;
cur->next = newhead;
newhead = cur;
cur = next;
}
return newhead;
}
📖Note:
next变量定义在循环外存在风险,因为原链表可能为空链表,cur->next就会造成空指针的访问,所以将next变量定义在循环内
思路二:转换链表指针的方向
对于头节点,其反转的步骤如下图
对于链表中的任意一个节点,反转步骤如下图
综上,我们需要三个指针,分别指向当前节点(n2),当前节点的前一个节点(n1)以及当前的节点的后一个节点(n3),n3用于存储下一个节点的位置
每次反转即n2->next = n1,n3=n2->next
迭代关系为:n1=n2;n2=n3;即三个指针每次向后依次移动一个节点
每一次反转都使n2和n1之间的指针关系反转,因此当n2指向尾节点时,n1指向尾节点的前一个节点,此次反转便是最后一次指针关系的反转,迭代后n2==NULL,所有反转结束,因此循环的条件是n2 != NULL
头节点的特殊之处:反转即使n2->next = NULL,所以我们可以将n1初始化为NULL,这样头节点也满足上述的反转关系
参考代码如下:
struct ListNode* reverseList(struct ListNode* head){
struct ListNode* n1 = NULL;
struct ListNode* n2 = head;
struct ListNode* n3 = NULL;
while(n2)
{
n3 = n2->next;
n2->next = n1;
//迭代
n1 = n2;
n2 = n3;
}
return n1;
}