golang实现单向链表反转
方法1:迭代法(推荐)
时间复杂度 O(n),空间复杂度 O(1)
实现步骤:
- 定义三个指针:
prev(前驱节点)、current(当前节点)、next(后继节点)。 - 遍历链表,逐个反转节点的指向。
 - 最终 
prev成为新链表的头节点。 
迭代法通过遍历原始链表,逐个将节点的指针指向其前一个节点,从而反转链表。
package main
import (
	"fmt"
)
// ListNode 定义链表节点
type ListNode struct {
	Val  int
	Next *ListNode
}
// reverseList 迭代法反转链表
func reverseList(head *ListNode) *ListNode {
	var prev *ListNode = nil
	curr := head
	for curr != nil {
		nextTemp := curr.Next // 保存当前节点的下一个节点
		curr.Next = prev      // 反转当前节点的指针
		prev = curr           // prev向前移动
		curr = nextTemp       // curr向前移动
	}
	return prev // 当curr为nil时,prev即为新的头节点
}
func main() {
	// 创建链表 1 -> 2 -> 3 -> 4 -> 5
	list := &ListNode{Val: 1}
	list2 := &ListNode{Val: 2}
	list.Next = list2
	list3 := &ListNode{Val: 3}
	list2.Next = list3
	list4 := &ListNode{Val: 4}
	list3.Next = list4
	list5 := &ListNode{Val: 5}
	list4.Next = list5
	reversedList := reverseList(list)
	/*for curr := reversedList; curr != nil; curr = curr.Next {
		fmt.Printf("%d ", curr.Val) // 输出反转后的链表:5 4 3 2 1
	}*/
	curr := reversedList
	for {
		if curr != nil {
			fmt.Printf("%d ", curr.Val) // 5 4 3 2 1
			curr = curr.Next
		} else {
			fmt.Println("\n输出完成")
			return
		}
	}
}
方法2:递归法
时间复杂度 O(n),空间复杂度 O(n)(递归栈深度)
实现步骤:
- 基线条件:链表为空或只有一个节点时,直接返回头节点。
 - 递归反转后续链表,并将当前节点连接到反转后的链表尾部。
 
递归法通过递归调用自身来实现反转,每次递归都将当前节点作为新的头节点返回,并逐步构建反转后的链表。
package main
import "fmt"
// ListNode 定义链表节点
type ListNode struct {
	Val  int
	Next *ListNode
}
// reverseListRecursively 递归法反转链表
func reverseListRecursively(head *ListNode) *ListNode {
	if head == nil || head.Next == nil {
		return head // 空链表或只有一个节点的链表直接返回自身作为新头节点
	}
	newHead := reverseListRecursively(head.Next) // 递归调用,反转剩余部分并获取新的头节点
	head.Next.Next = head                        // 将当前节点的下一个节点指向当前节点,实现反转
	head.Next = nil                              // 将当前节点的下一个节点置为nil,防止成环
	return newHead                               // 返回新的头节点
}
func main() {
	// 创建链表 1 -> 2 -> 3 -> 4 -> 5
	list := &ListNode{Val: 1}
	list2 := &ListNode{Val: 2}
	list.Next = list2
	list3 := &ListNode{Val: 3}
	list2.Next = list3
	list4 := &ListNode{Val: 4}
	list3.Next = list4
	list5 := &ListNode{Val: 5}
	list4.Next = list5
	reversedList := reverseListRecursively(list)
	/*for curr := reversedList; curr != nil; curr = curr.Next {
		fmt.Printf("%d ", curr.Val) // 输出反转后的链表:5 4 3 2 1
	}*/
	curr := reversedList
	for {
		if curr != nil {
			fmt.Printf("%d ", curr.Val) // 5 4 3 2 1
			curr = curr.Next
		} else {
			fmt.Println("\n输出完成")
			return
		}
	}
}
关键点总结
- 迭代法:通过三指针直接修改节点指向,无需额外空间,适合处理长链表。
 - 递归法:代码简洁,但递归深度与链表长度正相关,可能引发栈溢出。
 - 选择建议:优先使用迭代法,递归法仅用于理解递归思想或短链表场景。
 
两种方法各有优缺点,迭代法在空间复杂度上更优(只使用常量空间),而递归法在实现上更为简洁直观。可以根据具体需求和偏好选择使用哪一种方法。
                    
                
                
            
        
浙公网安备 33010602011771号