数据结构与算法
一、我们要到哪里去?
数据结构与算法,是很多人学编程的“拦路虎”。
但在 AI 时代,我们的目标不是死磕底层实现,而是学到能听懂、能抽象业务、能让 AI 正确实现的程度。
当你看完这篇,你应该能回答:
-
为什么要学数据结构与算法
-
数据结构有哪些、各自解决什么问题
-
常见算法的逻辑与应用场景
-
如何用 AI 在项目中快速调用这些“工具”
更重要的是,你能用生活例子把它们讲出来——因为它们本就是从现实抽象出来的。
二、AI编程速查表
| 结构/算法 | 特点 | 生活例子 | 编程场景 | 常用接口 |
|---|---|---|---|---|
| 数组 Array | 有序存储,可按下标访问 | 排好号的座位表 | 列表展示、分页数据 | push, pop, index |
| 对象 Object | 键值对存储 | 身份证信息 | 用户信息、配置 | key访问 |
| 队列 Queue | 先进先出 FIFO | 排队买票 | 消息队列、任务调度 | enqueue, dequeue |
| 栈 Stack | 后进先出 LIFO | 叠盘子 | 撤销功能、函数调用 | push, pop |
| 树 Tree | 分层结构 | 组织架构图 | 菜单、分类、权限系统 | 遍历、插入 |
| 图 Graph | 节点+关系 | 社交网络 | 路径规划、依赖关系 | 邻接表、遍历 |
| 排序 | 数据按规则排列 | 排座位 | 价格排序、时间排序 | sort |
| 搜索 | 找到目标元素 | 查字典 | 关键字搜索 | find, filter |
| 遍历 | 逐个访问数据 | 点名 | 数据处理 | forEach, map |
| 贪心 | 每步选最优 | 找零用最大面额 | 资源分配 | — |
| 动态规划 | 分解子问题 | 旅行计划 | 成本优化、调度 | — |
用法心法:先认出问题类型 → 找到匹配结构/算法 → 用 AI 生成 → 自己验证。
二、抽象的程度
汽车,对司机和修理工来说,是两种完全不同的存在。
-
修理工看到的是液压系统、传动装置、发动机结构。
-
司机看到的只是方向盘、油门、刹车和一个密闭的驾驶空间。
对司机来说,汽车就是一组接口(Interface):转动方向盘、踩油门,车辆就会按预期行驶。至于发动机内部是如何运转的,他完全不用关心。
编程也是如此。用户只在乎界面上的按钮和操作效果,而作为编程者,我们要设计出内部的逻辑,让这些按钮真正发挥作用。这就是抽象:隐藏复杂的实现细节,只暴露必要的操作接口。
程序员圈里有句老话:“不要重复造轮子”。意思是,如果你想让汽车跑起来,没必要自己打铁造轮胎——先看看有没有现成的轮子可以直接用。事实上,大多数复杂功能,别人已经写好并放在代码仓库中,我们只需调用即可,那些仓库就是一种抽象。
本节课同样是一个“抽象版本”的学习——我们不会去从零写出所有实现,而是学会识别、选择并调用已有的工具库,必要时让 AI 帮我们完成具体代码。
三、简单与复杂数据结构
数据,我们每天都在接触。
但如果要对它们分类呢?毕竟世界无限,而我们的描述能力有限,我们必须给这些数据贴上标签。
在业务场景中,你可能会遇到这样的信息:
-
用户姓名
-
订单日期
-
金额
-
是否付款
这些都是基本数据类型:
字符串(String)、日期(Date)、数值(Number)、布尔值(Boolean,表示是/否)
但是,只靠这些基本类型够吗?
假如你有 10 个订单,如何管理它们?一个聪明的做法是,把每个订单的信息打包在一起,例如:
订单1:
{
用户姓名: "Gobi Cowboy",
地址: "天宫一号",
日期: "20xx-xx-xx",
金额: "¥1,000,000,000.00"
},
订单2:
{
用户姓名: "张三",
...
},
...
订单10:
{
用户姓名: "李四",
...
}
恭喜你,这其实就是对象(Object)。
类似地,如果要存很多数字,可以用数组(Array):
array = [1, 2, 3, 2, 1]
使用这些复杂数据类型时,我们无需关心它的底层结构,只需通过**接口(Interface)**操作:
// 数组示例
arr = [1, 2, 3, 1, 1, 2]
arr[0] // 查找第1个元素(下标从0开始) → 1
arr[2] // 查找第3个元素 → 3
// 对象示例
obj = {
用户姓名: "Gobi Cowboy",
地址: "天宫一号",
日期: "20xx-xx-xx",
金额: "¥1,000,000,000.00"
}
obj.金额 // 读取金额 → ¥1,000,000,000.00
总结:
复杂数据类型就是对简单数据类型的一种封装。
它们让我们能更方便地组织和管理信息,而不用每次都从零开始构建结构。
四、常见的封装数据结构
如果你以为上面的数据结构可以解决我们的问题,那你就too young too simple了。接下来,我们将了解一些复杂的数据结构,而这些数据结构也是我们这堂课的主要对象。
1.队列(queue):
1.1 场景:
想象订单发货流程:必须按下单时间顺序来,一单一单处理,不能乱发。
如果每次都要人工找“下一个日期的订单”,不仅繁琐,还容易出错——于是,队列应运而生。
1.2 理论:
队列的特点:
- 先进先出(First in First out— FIFO)
- 只能从末尾插入
- 只能从前端弹出
队列开放的接口有以下四个:
- 入队(enqueue)
- 出队(dequeue)
- 查看队首(peek)
- 是否为空(isEmpty)
1.3 例子:
在计算机的世界里,微信发出的消息队列,网页上执行的事件循环(后面我们会讲到),广度优先搜索算法(BFS)储存的节点(后面会讲到)
现实生活中,例如马路上红绿灯路口的汽车,排队买票都是这样的例子。
那你的现实中,有没有其他的队列的例子呢?
1.4 小小的问题
如果队列中有插队的如何处理——可以查询‘优先级队列’
如果在超市,排队,我在末尾不想排了,或者有一个人直接结账了 ——可以查询‘双端队列’
2. 栈(stack)
2.1 场景:
我们来做一个思想实验:
假设你正在专心学习本教程,宝宝突然大哭 → 你去哄宝宝;
这时厨房水龙头又爆了 → 你去找修理工。
任务的执行顺序变成:
找修理工(最后发生 → 先处理)→ 哄宝宝 → 继续学习。
这是一个现实生活中的问题,但大家有没有发现和队列的区别,栈中最后的事情却要最先完成。
大家可以想想盘子的操作,最上面的盘子最先被使用。
2.2 理论:
栈的特点:
- 后入先出(Last in First out — LIFO)
开放的接口:
- 压栈(push)
- 出栈(pop)
- 栈顶(peek)
- 是否为空(isEmpty)
2.3 例子:
这种反直觉,我们称之为次序反转。
在计算机的世界应用非常的广泛,例如,递归(后面会讲到),浏览器的后退问题,括号的匹配问题,深度优先搜索(DFS,后面会讲到)等
在现实中,例如叠盘子,套娃(最里面的娃先开),文件的保存(放在最上面的是最先被使用的)
你发现了什么现实的例子呢?请记得打在评论区。
2.4 小小的问题
如果栈底的盘子一直没用,会落灰怎么办?(提示:这涉及队列与栈混合结构)
3. 树(Tree)
3.1 场景
假设你是一家几千人公司的 CEO,要画一张组织架构图。
用我们之前的数组或对象能不能表达?
——能,但很别扭。
因为公司不是扁平结构,而是有层级:
CEO → 总监 → 经理 → 小组长 → 员工。
一个员工只会有一个直接上司,但上司可以管理多人。
这种一对多、上下分层的关系,就需要用到一种全新的结构:树。
为什么叫“树”?把组织架构图倒过来看——CEO 是“树根”,员工是“树叶”,层层分支,形象吧?
3.2 理论
树是用来描述层级关系或一对多关系的数据结构。
它有几个特点:
-
根节点(Root):唯一的顶层节点(CEO)
-
子节点(Children):下属节点(经理的组员)
-
父节点(Parent):每个节点只能有一个直接上级
-
叶子节点(Leaf):没有下属的节点(普通员工)
-
无环性(No Cycle):不能既是上司又是下属
常用操作接口:
-
添加节点(Add Node) → 招新人
-
删除节点(Remove Node) → 离职
-
查找节点(Find Node) → 找“张三”
-
遍历(Traverse) → 打印全员名单
3.3 例子
-
计算机世界:文件系统(文件夹-文件)、网页 DOM 结构、AI 决策树
-
现实生活:公司组织架构、家族族谱、书籍目录结构
3.4 思考题
如果 CEO 想快速找到“张三”,并且知道他所在的部门和直接上司,用什么搜索方法最有效?
(提示:这涉及树的遍历算法)
4. 图(graph)
4.1 场景
树结构很强大,但能解决所有问题吗?
想象你要规划城市的地铁线路图:
-
“人民广场”站连接 1 号线、2 号线和 8 号线
-
你从“人民广场”出发,绕 2 号线一圈,还能回到“人民广场”
这里有两个特征:
-
多对多关系(一个站点连接多个站点)
-
存在环(走一圈又回到起点)
树结构只能处理单一层级、无环的关系,这种更复杂的网络,就需要更强大的结构——图(Graph)。
4.2 理论
图是用来描述多对多关系的最通用数据结构,树其实是没有环的特殊图。
组成:
-
节点(Vertex):实体,如城市、地铁站、网页
-
边(Edge):连接节点的关系
-
无向边(Undirected):双向关系(微信好友)
-
有向边(Directed):单向关系(微博关注)
-
带权重的边(Weighted Edge):边附带距离、时间、价格等信息
-
常用接口:
-
添加/删除节点(Add/Remove Vertex)
-
添加/删除边(Add/Remove Edge)
-
查找相邻节点(Get Neighbors)
-
查找路径(Find Path)
-
遍历图(DFS、BFS)
4.3 例子
-
计算机世界:
-
社交网络(用户=节点,好友关系=边)
-
互联网(网页=节点,超链接=边)
-
推荐系统(商品=节点,“也喜欢”关系=边)
-
-
现实生活:
-
地铁线路图
-
航空航线图
-
物流配送网络
-
人际关系网络(“六度空间理论”)
-
疾病传播路径
-
4.4思考题
如果你在北京,要去广州出差,路线可以飞机、高铁、甚至多次中转。面对这张城市(节点)+ 交通线路(带价格权重的边)组成的图,如何找到最低成本的出行方案?
(提示:Dijkstra 算法会帮你)