反转一个单链表,示例如下:
输入:
1 -> 2 -> 3 -> 4 -> 5
输出:
5 -> 4 -> 3 -> 2 -> 1
- 链表是只允许顺序访问的线性顺序结构, 这里强调这个, 因为后续在链表断开的时候, 需要用到temp变量存储断开的后续链表就是这个原因.
- 链表之间通过指针相连, 指针访问, 每个节点仅有一个指针
- 链表的尾节点也有指针, 指向null, 这是我们做题遍历循环终止的一个重要条件.
这题目有多种解题思路, 本篇着重使用迭代法完成链表的反转.
当使用迭代法反转链表时,我们使用两个指针:prev
和 current
,以及一个额外的指针next来帮助反转过程。
prev指向给定链表头节点的前一个位置,? 初始化设置成null, 可以理解成一个新的链表, 最终的目的也是需要将prev变成反转后的链表.
current一开始指向给定链表的头节点, 然后挨个往后顺序移动, 直到current节点为空.
next用来表示current之后的链表.??我们现在来看一下逐步循换一步一步往prev头节点插入值和指向的方式变成一个反转后的链表.
完成反转的思想是在current当前节点,先存储current.next的链表为temp临时变量,?然后切断current与current.next的指向,将current.next的指向转变成指向prev(指针转换方向), 再把current赋值给prev(赋值的目的就是让prev成为反转后的链表),?最后更新current的值为temp, 继续下一次同样的操作, 直到current为null, 循环终止.
这样理解起来有点困难, 看一下反转在每一个循环步骤里的数据变化, 就可以明白了.
原始链表:?
1 -> 2 -> 3 -> 4 -> 5
每一次循环的判断条件: current节点不能为空, 为空说明已经遍历到了链表的最后位置
每一次循环必做的事情:?
temp存储current.next, 切掉current与current.next的指向, 指向prev,再将current赋值给prev, 最后更新current的值更新成temp.初始化:
prev: null
current的值是1, current表示的链表是1?
-> 2 -> 3 -> 4 -> 5
current.next的值是2, temp表示的链表是?2 -> 3 -> 4 -> 5
第一次循环过程:
- temp存储current.next, 因此temp的值是2 -> 3 -> 4 -> 5
- 切掉current与current.next的指向, 指向prev, 因此current的值是?1 , 对应的链表?1
-> null
- 再将current赋值给prev, 因此 prev的值是1, 对应的链表?1?
-> null
- 更新current的值为temp, current对应的值是2, 对应的链表??
2 -> 3 -> 4 -> 5
第二次循环过程:
- temp存储current.next, 因此temp的值是
?3 -> 4 -> 5
- 切掉current与current.next的指向, 指向prev, 因此current的值是 2?, 对应的链表
? ?2
->
1-> null
- 再将current赋值给prev, 因此 prev的值是2, 对应的链表 2?
->
1-> null
- 更新current的值为temp, current对应的值是3, 对应的链表?
3 -> 4 -> 5
第三次循环过程:
- temp存储current.next, 因此temp的值是
?4 -> 5
- 切掉current与current.next的指向, 指向prev, 因此current的值是 3?, current对应的链表
? ?3?
->
2->
1-> null
- 再将current赋值给prev, 因此 prev的值是3, prev对应的链表 3
->
2->
1-> null
- 更新current的值为temp, current对应的值是4, current对应的链表?
4 -> 5
第四次循环过程:
- temp存储current.next, 因此temp的值是
?5
- 切掉current与current.next的指向, 指向prev, 因此current的值是 4, current对应的链表
? 4
->
3?->
2->
1-> null
- 再将current赋值给prev, 因此 prev的值是4, prev对应的链表 4
->
3->
2->
1-> null
- 更新current的值为temp, current对应的值是5, current对应的链表?
?5
第五次循环过程:
- temp存储current.next, 因此temp的值是
?null
- 切掉current与current.next的指向, 指向prev, 因此current的值是 5, current对应的链表
? 5?
->?
4->
3?->
2->
1?-> nul
- 再将current赋值给prev, 因此 prev的值是4, prev对应的链表? 5?
->?
?4?->
3->
2->
1?-> null
- 更新current的值为temp, current对应的值是null, 循环结束
public class ReverseLinkedListPointer {
/**
* 反转链表
*
* @param head 头节点
* @return 反转后的头节点
*/
public ListNode reverse(ListNode head) {
// 初始化前一个节点为null,因为反转后的最后一个节点指向null
ListNode prev = null;
// 初始化当前节点为头节点
ListNode current = head;
// 遍历链表
while (current != null) {
// 暂存当前节点的下一个节点,防止丢失链表信息
ListNode next = current.next;
// 将当前节点的next指向前一个节点,实现反转
current.next = prev;
// 赋值给prev, 更新新链表
prev = current;
//current指针到下一位置
current = next;
}
// 返回反转后的头节点
return prev;
}
}