声明
这篇文章是看了“左程云”老师在b站上的讲解之后写的, 自己感觉已经能理解这个题目了, 所以就将整个过程写下来, 下面的两段代码是直接可以运行的.
这个是“左程云”老师个人空间的b站的链接, 数据结构与算法讲的很好很好, 希望大家可以多多支持左程云老师, 真心推荐.
https://space.bilibili.com/8888480?spm_id_from=333.999.0.0
顺便提供一下测试链接:
https://leetcode.cn/problems/reverse-linked-list/
1. 解释“指向”问题
pre.next = cur1;
上面的代码是修改指向的问题,
其中, 左边的是需要重新指向(被修改)的, 右边的是被指向的.
翻译一下就是:将 pre
下一个指向的节点修改为 cur1
.
2. 详细解释 next
的作用
pre.next = cur1;
这段代码的意义是:将 pre
指向的下一个节点更换为 cur1
;
-
pre.next
在左边时,表示pre
本身需要指向的下一个节点。
-
pre.next
在右边时,表示pre
当前指向的下一个节点。
所以这个是一个问题, 要区分清楚, next
是被修改还是被指向.
3. 对代码的解释
3.1 思路
- 先设置一个头结点, 用来接受传过来的“链表”.
- 然后设置两个“指针”,
pre(previous:上一个)
,next(下一个)
, 并且都设置为null
. - 然后进入循环, 终止条件是:“
head == null
” - 然后将
next
指向下一个节点. - 然后将
head
指向的节点的指针指向上一个节点pre
. - 然后将
pre
指针指向当前的haed
, (作用是:为下一次的迭代做铺垫) - 最后将
head
指向next
指向的节点. 然后进行下一次循环. - 当
head == null
之后, 返回pre
. 这样就完成了“链表”的翻转.
public static ListNode reverseList(ListNode head) {
ListNode pre = null;
ListNode next = null;
while (head != null) {// 截止条件是head指向null;
next = head.next; // 1. 先将next指针指向下一个节点;
head.next = pre; // 2. 然后将head指向的节点的指针指向上一个节点;
pre = head; // 3. 然后将pre指针指向head指向的节点(作用是:为下一次的迭代做铺垫);
head = next; // 4. 最后将head指针指向next指向的节点, 这样就可以进行下一次循环了.
}
return pre;
}
3.2 对这个方法进行测试
设置一段链表, 进行测试, 对于这个方法进行实现.
public class MySingleListReverse {
// 单链表节点
public static class ListNode {
public int val;
public ListNode next;
public ListNode(int val) {
this.val = val;
}
public ListNode(int val, ListNode next) {
this.val = val;
this.next = next;
}
}
// 反转单链表
public static ListNode reverseList(ListNode head) {
ListNode pre = null;
ListNode next = null;
while (head != null) {
//注意这里:赋值方面的问题(引用数据类型),
//“=”号左边的是你要修改的地方, “=”右边的是你需要指向的地方.
next = head.next;
//next的问题说明:
//若是将带着“next”的放到左边, 说明修改在本身(head)上修改,
//若是将带着“next”的放到右边, 说明是将本身指向next指向的位置
head.next = pre;
pre = head;
head = next;
}
return pre;
}
// public static ListNode reverseList(ListNode head) {
// ListNode pre = null;
// ListNode next = null;
// while (head != null) {// 截止条件是head指向null;
// next = head.next; // 1. 先将next指针指向下一个节点;
// head.next = pre; // 2. 然后将head指向的节点的指针指向上一个节点;
// pre = head; // 3. 然后将pre指针指向head指向的节点(作用是:为下一次的迭代做铺垫);
// head = next; // 4. 最后将head指针指向next指向的节点, 这样就可以进行下一次循环了.
// }
// return pre;
// }
// 打印链表
public static void printList(ListNode head) {
ListNode current = head;
while (current != null) {
System.out.print(current.val + " ");
current = current.next;
}
System.out.println();
}
public static void main(String[] args) {
// 创建一个单链表: 1 -> 2 -> 3 -> 4 -> 5
// 第一种方式
// ListNode head = new ListNode(1);
// head.next = new ListNode(2);
// head.next.next = new ListNode(3);
// head.next.next.next = new ListNode(4);
// head.next.next.next.next = new ListNode(5);
// 第二种方式
ListNode list1 = new ListNode(1);
ListNode list2 = new ListNode(2);
ListNode list3 = new ListNode(3);
ListNode list4 = new ListNode(4);
ListNode list5 = new ListNode(5);
list1.next = list2;
list2.next = list3;
list3.next = list4;
list4.next = list5;
// 打印原始链表
System.out.println("原始链表:");
printList(list1);
// 反转链表
ListNode reversedHead = reverseList(list1);
// 打印反转后的链表
System.out.println("反转后的链表:");
printList(reversedHead);
}
}