一、链表反转的三个方法以及优缺点
1.1 方法介绍及代码示例
链表反转,也称为链表逆置,是指将链表中的节点顺序颠倒过来,使得原来的头节点变成尾节点,尾节点变成头节点,同时每个节点的指针指向它的前一个节点。这个操作在计算机科学中非常常见,尤其是在数据结构和算法的学习和应用中。
链表反转的基本思想是遍历原链表,逐个更改节点的指针方向。具体来说,有以下几种常见的方法:
-
迭代法:使用三个指针,分别指向当前节点、当前节点的前一个节点和当前节点的下一个节点。在遍历链表时,逐个更改当前节点的指针,使其指向前一个节点。
-
递归法:从链表的尾部开始,递归地将每个节点的下一个节点指向自己,同时将自己的指针域设置为null,直到链表的头部。
-
头插法:创建一个新的空链表,遍历原链表,将每个遍历到的节点插入到新链表的头部,最终新链表就是原链表的反转。
下面是一个使用python实现的链表反转的迭代法示例代码
def reverse_list(head):
"""反转链表的函数。
参数:
head (ListNode): 链表的头节点。
返回:
ListNode: 反转后的链表的头节点。
"""
prev = None # 初始化前一个节点为None。
current = head # 当前节点设置为头节点。
while current:
next_node = current.next # 保存当前节点的下一个节点。
current.next = prev # 将当前节点的next指向前一个节点,实现反转。
prev = current # 前一个节点前移。
current = next_node # 当前节点前移。
return prev # 返回反转后的链表的头节点。
核心思想就是设立三个指针变量,然后不断的去迭代
举个例子就是1-2-3-4-5这个链表
我们设立一个指针变量prev去指向1的前一个结点null,用current指向头节点1,用next_node指向后续的结点,然后我们去改变current的next指向到1,把prev和current的指向往后移动就可以了,直到循环结束
下面是一个使用python实现的链表反转的递归法示例代码
def reverse_list_recursive(head):
"""递归反转链表的函数。
参数:
head (ListNode): 链表的头节点。
返回:
ListNode: 反转后的链表的头节点。
"""
# 递归终止条件:如果头节点为空或者下一个节点为空,返回头节点
if not head or not head.next:
return head
# 递归调用,反转从第二个节点开始的子链表
new_head = reverse_list_recursive(head.next)
# 将当前节点的下一个节点的next指针指向当前节点,实现反转
head.next.next = head
# 将当前节点的next指针置为空,防止链表循环
head.next = None
# 返回反转后的链表的头节点
return new_head
这段递归反转链表的代码的执行过程可以分解为以下步骤:
-
递归终止条件:函数首先检查是否已经到达链表的末尾(即
head
为空,或者head.next
为空)。如果是,就返回head
,因为这时候没有更多的节点需要反转。 -
递归调用:如果不满足终止条件,函数会递归地调用自己,传入当前节点的下一个节点
head.next
。这个调用会一直进行,直到到达链表的末尾。 -
反转指针:当递归开始返回时,每次返回都会到达一个新的节点。在这个时候,代码
head.next.next = head
会执行,这实际上是将当前节点的下一个节点的next
指针指向当前节点,从而实现了反转。 -
断开连接:为了防止链表出现循环,需要将当前处理的节点的
next
指针设置为None
,即head.next = None
。 -
返回新头节点:递归函数最终返回
new_head
,这是反转后链表的头节点。
让我们通过一个具体的例子来说明这个过程:
假设我们有一个链表 1 -> 2 -> 3 -> 4 -> 5
。
- 当
reverse_list_recursive
首次被调用时,head
指向节点1。 - 递归调用
reverse_list_recursive(head.next)
,此时head.next
指向节点2。 - 这个过程会一直继续,直到到达节点5,此时
head.next
为空,触发递归终止条件,开始返回。 - 在返回的过程中,节点5的
next
指针会指向节点4,节点4的next
指针会指向节点3,依此类推。 - 最后,节点1的
next
指针会被设置为None
,因为它现在是链表的最后一个节点。 new_head
最终指向节点5,这现在是反转后链表的头节点。
通过这个递归过程,原始链表的头节点变成了新链表的尾节点,原始链表的尾节点变成了新链表的头节点,从而实现了链表的反转。🔄
下面是一个使用python实现的链表反转的头插法示例代码
def reverse_list_head_insertion(head):
"""使用头插法反转链表的函数。
参数:
head (ListNode): 链表的头节点。
返回:
ListNode: 反转后的链表的头节点。
"""
new_head = None # 新链表的头节点,开始时为空。
current = head # 当前节点设置为原链表的头节点。
while current:
next_node = current.next # 保存当前节点的下一个节点。
current.next = new_head # 将当前节点的next指针指向新链表的头节点。
new_head = current # 更新新链表的头节点为当前节点。
current = next_node # 移动到原链表的下一个节点。
return new_head # 返回反转后的链表的头节点。
# 示例用法
# 创建链表 1 -> 2 -> 3 -> 4 -> 5
head = ListNode(1, ListNode(2, ListNode(3, ListNode(4, ListNode(5)))))
# 反转链表
reversed_list = reverse_list_head_insertion(head)
# 打印反转后的链表
current = reversed_list
while current:
print(current.value)
current = current.next
在这个代码中,我们创建了一个新的链表new_head
,它最初是空的。然后我们遍历原始链表,每次迭代都将当前节点current
插入到新链表的前端。这样,当我们完成遍历后,new_head
就成了反转后链表的头节点。🔄