Go 数据结构入门:线性表、顺序表、链表
文章目录
- Go 数据结构入门:线性表、顺序表、链表
- 一、什么是线性表?(一句话记住)
- 二、先看懂:内存长什么样(外层容器)
- 三、顺序表:内存中「连续存放」
- 🔥 内存布局图(外层容器 \+ 内层连续)
- 特点
- 优点
- 缺点
- Go 中的顺序表 = 切片 slice
- 四、链表:内存中「不连续、散落存放」
- 🔥 内存布局图(外层容器 \+ 内层散落)
- 每个节点结构
- 特点
- 优点
- 缺点
- Go 实现简单链表
- 五、最强对比:顺序表 vs 链表
- 🔥 一眼看懂内存区别
- 六、零基础总结(3 句话背会)
Go 数据结构入门:线性表、顺序表、链表
大家好~前面我们学习了 Go 基础、指针,今天正式进入数据结构。
很多同学觉得数据结构抽象难懂,我这篇用「外层内存容器 + 内层格子布局」画图讲解,一眼看清顺序表连续、链表不连续,零基础一遍看懂!
全篇包含:
✅ 什么是线性表(超级通俗)
✅ 顺序表:内存连续存放(结构图)
✅ 链表:内存不连续、散落存放(结构图)
✅ 顺序表 vs 链表 最强对比
✅ Go 代码演示
✅ 面试必问总结
一、什么是线性表?(一句话记住)
线性表 = 排成一条直线的元素序列。
就像:排队、一串珠子、一列火车…
特点:
有先后顺序
有第一个、最后一个
中间每个元素:前面叫前驱,后面叫后继
线性表只是逻辑结构,真正在内存里有两种实现:
1️⃣顺序表(连续放)
2️⃣链表(分开放,指针连)
二、先看懂:内存长什么样(外层容器)
我们把整个内存画成一个大矩形容器,里面是一个个带地址的小格子:
每个格子 = 1 字节,有唯一地址。
┌─────────────────────────────────────────────┐ │ 系统内存 │ ← 外层大容器 │ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ │ │ │0x01 │ │0x02 │ │0x03 │ │0x04 │ │0x05 │ │ │ └─────┘ └─────┘ └─────┘ └─────┘ └─────┘ │ │ │ │ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ │ │ │0x06 │ │0x07 │ │0x08 │ │0x09 │ │0x10 │ │ │ └─────┘ └─────┘ └─────┘ └─────┘ └─────┘ │ └─────────────────────────────────────────────┘所有数据结构,本质就是:
怎么在这些格子里摆放数据。
三、顺序表:内存中「连续存放」
顺序表 =一整块连续内存,元素紧紧挨在一起。
🔥 内存布局图(外层容器 + 内层连续)
┌─────────────────────────────────────────────┐ │ 内存 │ │ │ │ ┌─────┬─────┬─────┬─────┬─────┐ │ │ │ 10 │ 20 │ 30 │ 40 │ 50 │ │ │ └─────┴─────┴─────┴─────┴─────┘ │ │ ↑ 完全连续、紧凑挨着 │ │ │ └─────────────────────────────────────────────┘特点
元素物理地址连续
支持随机访问(下标直接取,O (1))
优点
✅ 查找快
✅ 内存紧凑,无额外开销
缺点
❌ 插入 / 删除慢:后面元素要整体移动
❌ 需要一大块连续内存,内存不足易分配失败
Go 中的顺序表 = 切片 slice
packagemainimport"fmt"funcmain(){// 切片本质就是顺序表(连续内存)arr:=[]int{10,20,30,40,50}// 随机访问 O(1)fmt.Println(arr[2])// 30}四、链表:内存中「不连续、散落存放」
链表 =元素可以散落在内存任意位置,只用指针串起来。
就像小朋友手拉手,不用站在一起。
🔥 内存布局图(外层容器 + 内层散落)
┌─────────────────────────────────────────────┐ │ 内存 │ │ │ │ ┌──────┐ ┌──────┐ ┌──────┐ │ │ │ 10 │ │ 20 │ │ 30 │ │ │ │ Next├──────────→│ Next├────→│ Next├─→nil│ │ └──────┘ └──────┘ └──────┘ │ │ ↑ 不连续 ↑ 不连续 │ └─────────────────────────────────────────────┘每个节点结构
┌─────────────────────┐ │ 数据域 │ ← 存值 │ 指针域 │ ← 存下一个节点地址 └─────────────────────┘特点
物理空间不连续
逻辑连续(靠 Next 指针串联)
优点
✅ 插入 / 删除极快:只改指针
✅ 不需要连续内存,碎片利用率高
✅ 可随时无限扩容
缺点
❌ 查找慢:必须从头遍历
❌ 每个节点多存一个指针,额外开销
Go 实现简单链表
packagemainimport"fmt"// 定义链表节点typeNodestruct{ValintNext*Node}funcmain(){// 构建 10 → 20 → 30n1:=&Node{Val:10}n2:=&Node{Val:20}n3:=&Node{Val:30}n1.Next=n2 n2.Next=n3// 遍历链表cur:=n1forcur!=nil{fmt.Println(cur.Val)cur=cur.Next}}五、最强对比:顺序表 vs 链表
🔥 一眼看懂内存区别
【顺序表:连续】 ┌─────────────────────────────────┐ │ 内存 │ │ ┌─────┬─────┬─────┬─────┐ │ │ │ 10 │ 20 │ 30 │ 40 │ │ │ └─────┴─────┴─────┴─────┘ │ └─────────────────────────────────┘ 【链表:不连续】 ┌─────────────────────────────────────────────┐ │ 内存 │ │ ┌─────┐ ┌─────┐ ┌─────┐ │ │ │ 10 │ │ 20 │ │ 30 │ │ │ └──┬──┘ └──┬──┘ └──┬──┘ │ │ └──────────────└──────────────┘ │ │ 指针连接,物理位置完全不连续 │ └─────────────────────────────────────────────┘| 维度 | 顺序表 | 链表 |
|---|---|---|
| 内存布局 | 连续 | 不连续、散落 |
| 查找 | 快 O (1) | 慢 O (n) |
| 插入 / 删除 | 慢(需要移动数据) | 快(只改指针) |
| 内存占用 | 小(无额外开销) | 大(每个节点存指针) |
| 扩容 | 需重新分配连续内存 | 随时加节点 |
| 适用场景 | 查询多、增删少 | 增删多、频繁插入 |
六、零基础总结(3 句话背会)
线性表 = 排成一条直线的元素
顺序表 = 内存连续存放,查找快、增删慢
链表 = 指针连接,增删快、查找慢
👍点赞 + ⭐收藏 + 📌关注,更新第一时间不迷路!
(注:文档部分内容可能由 AI 生成)
