掘金 后端 ( ) • 2024-04-25 09:52

单向链表介绍

什么是单向链表

单向链表是一种常见的数据结构,它由一系列节点组成,每个节点包含两个部分:数据域和指针域。数据域用于存储数据,而指针域则指向链表中的下一个节点,这种结构使得链表中的元素可以非连续地存储在内存中,而通过每个节点的指针链接到一起。

单向链表的特点

  • 动态数据结构:单向链表在运行时可以动态地插入和删除节点,不需要预先知道数据量的大小,相比于数组有更好的内存利用率。
  • 节省空间:除了数据之外,每个节点只需要存储一个指向其后继节点的指针。
  • 灵活的内存分配:节点可以在内存中任意位置,增加和删除节点不需要移动其他元素。

单向链表的操作

单向链表的基本操作通常包括:

  • 插入节点:可以在链表的头部、尾部或指定位置插入新的节点。
  • 删除节点:可以删除链表的头节点、尾节点或指定位置的节点。
  • 搜索节点:根据条件遍历链表查找节点。
  • 遍历链表:从头到尾访问每个节点的数据。

Go语言实现单向链表

下面我们将使用Go语言来实现一个基本的单向链表数据结构和几个常用方法。

image.png

定义链表节点和链表结构

首先,定义一个ListNode结构,代表链表中的一个节点,以及一个LinkedList结构,代表整个链表:

package main

import "fmt"

// ListNode 定义链表节点
type ListNode struct {
    Value int
    Next  *ListNode
}

// LinkedList 定义链表结构
type LinkedList struct {
    Head *ListNode
}

实现链表的基本操作

插入节点

  • 在链表头部插入节点
func (l *LinkedList) InsertAtHead(value int) {
    node := &ListNode{Value: value}
    if l.Head != nil {
        node.Next = l.Head
    }
    l.Head = node
}
  • 在链表尾部插入节点
func (l *LinkedList) InsertAtTail(value int) {
    node := &ListNode{Value: value}
    if l.Head == nil {
        l.Head = node
        return
    }
    current := l.Head
    for current.Next != nil {
        current = current.Next
    }
    current.Next = node
}

删除节点

  • 删除头节点
func (l *LinkedList) DeleteHead() {
    if l.Head != nil {
        l.Head = l.Head.Next
    }
}

遍历链表

  • 打印链表所有节点
func (l *LinkedList) Print() {
    current := l.Head
    for current != nil {
        fmt.Print(current.Value, " ")
        current = current.Next
    }
    fmt.Println()
}

测试链表操作

最后,我们来测试一下这个链表的实现:

package main

import "fmt"

// ListNode 定义链表节点
type ListNode struct {
	Value int
	Next  *ListNode
}

// LinkedList 定义链表结构
type LinkedList struct {
	Head *ListNode
}

func (l *LinkedList) InsertAtHead(value int) {
	node := &ListNode{Value: value}
	if l.Head != nil {
		node.Next = l.Head
	}
	l.Head = node
}

func (l *LinkedList) InsertAtTail(value int) {
	node := &ListNode{Value: value}
	if l.Head == nil {
		l.Head = node
		return
	}
	current := l.Head
	for current.Next != nil {
		current = current.Next
	}
	current.Next = node
}

func (l *LinkedList) DeleteHead() {
	if l.Head != nil {
		l.Head = l.Head.Next
	}
}

func (l *LinkedList) Print() {
	current := l.Head
	for current != nil {
		fmt.Print(current.Value, " ")
		current = current.Next
	}
	fmt.Println()
}

func main() {
	list := LinkedList{}
	list.InsertAtHead(1)
	list.InsertAtTail(2)
	list.InsertAtHead(0)
	list.Print() // 输出应为 0 1 2

	list.DeleteHead()
	list.Print() // 输出应为 1 2
}

image.png

总结和未来展望

通过上述代码,我们成功实现了一个简单的单向链表,并展示了如何在Go语言中操作链表的基本功能。单向链表是学习更复杂数据结构如双向链表和循环链表的基础。在实际应用中,理解和能够实现基本数据结构是非常重要的,它们是构建更复杂系统的基石。