题目来源:
题目描述:
代码实现
1、方法一
struct ListNode* reverseList(struct ListNode* head) { struct ListNode* prev = NULL, * cur = head; while (cur) { struct ListNode* next = cur->next; //头插 cur->next = prev; prev = cur; //迭代 cur = next; } return prev; }
1.1分析
方法一是头插法。
创建三个结构体指针变量:prev、cur、next。
我们先置空 prev,将头指针 head 存放在 cur 中,next 存放 cur 的 next。第一次 cur 的 next 赋值为 prev 就是空,next 指向 cur的next,prev 指向当前的 cur。不断循环,当 cur 为空时就将整个链表反转完成了。
重点:
1.循环:next = cur->next; cur->next = prev; prev = cur; cur = next; 这个循环体的顺序是不可以交换的。 循环条件应该是 cur != NULL 时就进入循环,等于 NULL 的话就说明全部的结点头插已经完成了。
2.返回值:因为是头插,prev 一直指向头结点,所以返回 prev。return prev;
2、方法二
struct ListNode* reverseList(struct ListNode* head) { if(head == NULL) return NULL; struct ListNode* n1 = NULL, * n2 = head, * n3 = n2->next; while (n2) { n2->next = n1; n1 = n2; n2 = n3; if(n2 != NULL) n3 = n3->next; } return n1; }
2.1 分析
方法二是逆置法,将开始向右的箭头改为向左就逆置成功了。
创建三个结构体指针变量:n1、n2、n3。
先置空 n1 ,将 head 存放在 n2 中,n3 保存 n2的next。将 n2的next 指向 n1,这样就可以让头结点的next指向空;然后将 n1 赋值为 n2;再将 n2 赋值为 n3;n2 如果指向的结点不为空,n3 就在自己的基础上再往后走一步。
重点:
1.如果原链表为空,就返回NULL;
2.循环:n2->next = n1; n1 = n2; n2 = n3; n3 = n3->next; 这个循环体的顺序是不可以交换的。以我们的图来看,当 n2 为空的时候循环停止,因此循环条件为 n2(n2 != NULL 与 n2 是一样的)。
3.返回值:我们的 n2 走到 NULL 的时候,n1 正好就指向了原链表的尾结点,因为是逆置,所以返回的就是尾结点。return n1;
4.循环体中,最后一次改变 n3 时 n3 已经是空了,再让 n3 = n3 ->next, 会出现空指针问题,因此我们在 n3 的改变上加一个判断条件 n3 != NULL,如果为空 n3 就不再往后移了。