目录
[3.1 数组](#3.1 数组)
[3.2 切片](#3.2 切片)
一.引言
上篇文章介绍了最基本的数据结构数组,与数组紧密相关的就是链表了,本文介绍 Go 语言中链表如何实现。
二.链表
Go 语言的链表实现在标准库的 container/list 代码包中。这个代码包中有两个公开的程序实体 List 和 Element,List 实现了一个双向链表(以下简称链表),而 Element 则代表了链表中元素的结构。
Go
package main
import (
"container/list"
"fmt"
)
func main() {
// 创建一个新的链表
l := list.New()
// 在链表的尾部添加元素
l.PushBack("Go")
l.PushBack("is")
l.PushBack("awesome")
// 在链表的头部添加元素
l.PushFront("Programming")
// 遍历链表并打印元素
for e := l.Front(); e != nil; e = e.Next() {
fmt.Println(e.Value)
}
}
使用 PushBack 在链表尾部添加元素,类似 python 数组的 append 方法。
使用 PushFront 在链表的头节点添加元素,类似 python 数组的 insert(0) 方法。
三.数组与切片
这里也趁机比较下数组、切片的形式。
3.1 数组
数组是固定长度的序列,存储相同类型的元素。
Go
package main
import "fmt"
func main() {
// 定义一个数组
var arr [3]string
arr[0] = "Go"
arr[1] = "is"
arr[2] = "awesome"
// 遍历数组并打印元素
for i := 0; i < len(arr); i++ {
fmt.Println(arr[i])
}
}
3.2 切片
切片是动态数组,可以根据需要增长和缩减。
Go
package main
import "fmt"
func main() {
// 定义一个切片
slice := []string{"Go", "is", "awesome"}
// 添加元素
slice = append(slice, "and", "powerful")
// 遍历切片并打印元素
for i := 0; i < len(slice); i++ {
fmt.Println(slice[i])
}
}
四.链表、数组和切片的比较
1.相同点
- 存储类型
链表、数组和切片都用于存储相同类型的元素
- 遍历
都可以通过循环遍历元素
2.不同点
- 长度
数组: 长度固定,必须指定长度
切片: 长度可变,可以动态增长和缩减
链表: 长度可变,可以动态添加和删除元素
- 内存使用
数组: 连续内存块,访问速度快
切片: 基于数组实现,底层是数组,具有动态增长特性
链表: 非连续内存块,每个元素包含指针,内存开销较大
- 操作效率
数组: 随机访问效率高,但插入和删除效率低,需要移动元素
切片: 随机访问效率高,插入与删除效率高于数组,但仍需要移动元素
链表: 插入和删除操作效率高,只需修改指针,但随机访问效率低,需要遍历
五.总结
数组: 适用于固定长度且高效随机访问的场景
切片: 适用于需要动态长度且高效随机访问的场景
链表: 适用于需要频繁插入和删除的场景
通过分析,我们看到几种结构主要是在读写效率和增删效率上的区别,根据自己的业务场景,选择合适的数据结构来解决问题。