链表反转的算法有很多,这里介绍一种笔者认为最简单的:头插法。
头插法的思路是这样的:
假设原始链表为:
链表节点A ——> 链表节点B ——> 链表节点C
1、声明一个暂存节点tmp
2、将链表节点A的地址赋给 暂存节点tmp.next
此时的链表图示为:
暂存节点tmp ——> 链表节点A
链表节点B ——> 链表节点C
3、将链表节点B的地址赋给暂存节点tmp.next,并将链表节点A的地址赋给链表节点B的next
此时链表图示变为:
暂存节点tmp ——>链表节点B ——> 链表节点A
链表节点C
4、将链表节点C的地址赋给暂存节点tmp.next,并将链表节点B的地址赋给链表节点C的next
此时链表图示变为:
暂存节点tmp ——> 链表节点C ——> 链表节点B ——> 链表节点A
输出tmp.next就好了~~~
具体代码如下:
#include "pch.h"
#include <iostream>
//定义链表节点
struct ListNode {
int val;
ListNode *next;
ListNode() : val(0), next(nullptr) {}
ListNode(int x) : val(x), next(nullptr) {}
ListNode(int x, ListNode *next) : val(x), next(next) {}
};
void list_print(ListNode * head, const char* name) {
printf("print list : %s", name);
if (!head) {
printf("list is NULL");
return;
}
else {
while (head)
{
printf("%d", head->val);
head = head->next;
}
}
}
class Solution {
public:
ListNode* reverseList(ListNode* head) {
//这里要注意:tmp不是指针型的!因为如果定义为指针型的tmp,
//在进行第一次循环的时候,tmp——>next会出现不合理指针,导致程序报错
ListNode tmp = NULL;
while (head) {
ListNode * next = head->next;
head->next = tmp.next;
tmp.next = head;
head = next;
}
return tmp.next;
}
};
int main()
{
ListNode a, b, c, d, e;
a.val = 1;
b.val = 2;
c.val = 3;
d.val = 4;
e.val = 5;
a.next = &b;
b.next = &c;
c.next = &d;
d.next = &e;
Solution obj;
ListNode * newhead = obj.reverseList(&a);
list_print(newhead, "mylist");
}
输出的就是反转之后的链表了。
在做这个题的时候,对于指针的认识又加深了,其实指针就是内存地址的一个表征,比如本例中,在把某个节点的地址赋值给next指针以后,next指针就可以表征该地址,从而完成访问的功能。