单链表反转
反转链表,又可以称为翻转或逆置链表,它们表达的是同一个意思。以图 1 所示的链表为例:
经过反转(翻转、逆置)后,得到的新链表如图 2 所示:
以上图为例,单链表的反转重点在于每个节点的指针要由原来的右指向变为左指向。那么就需要遍历一次链表,并在遍历的过程中对指针的指向进行改动。
接下来图解一下遍历过程以及思路
以图 1 中建立的链表为例,首先我们定义 3 个指针并分别命名为 beg、mid、end。它们的初始指向如图 3 所示:
在上图的基础上,遍历链表的过程就等价为:3 个指针每次各向后移动一个节点,直至 mid 指向链表中最后一个节点(此时 end 为 NULL )。需要注意的是,这 3 个指针每移动之前,都需要做一步操作,即改变 mid 所指节点的指针域,另其指向和 beg 相同。本来mid的指针指向了第2个节点,现在要操作一下,让它指向NULL,这样就做到了指针指向的改动。
在图 3 的基础上,我们先改变 mid 所指节点的指针域指向,另其和 beg 相同(即改为 NULL),然后再将 3 个指针整体各向后移动一个节点。整个过程如图 4 所示:
在图 4 基础上,先改变 mid 所指节点的指针域指向,另其和 beg 相同(指向节点 1 ),再将 3 个指针整体各向后移动一个节点。整个过程如图 5 所示:
在图 5 基础上,先改变 mid 所指节点的指针域指向,另其和 beg 相同(指向节点 2 ),再将 3 个指针整体各向后移动一个节点。整个过程如图 6 所示:
图 6 中,虽然 mid 指向了原链表最后一个节点,但显然整个反转的操作还差一步,即需要最后修改一次 mid 所指节点的指针域指向,另其和 beg 相同(指向节点 3)。如图 7 所示:
注意,这里只需改变 mid所指节点的指向即可,不用再次移动3个指针。
//迭代反转法,head 为无头节点链表的头指针
link * iteration_reverse(link* head) {
if (head == NULL || head->next == NULL) {
return head;
}
else {
link * beg = NULL;
link * mid = head;
link * end = head->next;
//一直遍历
while (1) //为什么不用while(end)呢?要注意,在end==null的时候还有一次mid指针转向的操作
{
//修改 mid 所指节点的指向
mid->next = beg;
//此时判断 end 是否为 NULL,如果成立则退出循环
if (end == NULL) {
break;
}
//整体向后移动 3 个指针
beg = mid;
mid = end;
end = end->next;
}
//最后修改 head 头指针的指向
head = mid;
return head;
}
}
单链表反转还有很多种操作Here,这里就不一一叙述了,感兴趣的同学可以参考。