文章目录
-
- 一、什么是程序?
- 二、什么是数据结构?
-
- [1. 数据结构是什么?](#1. 数据结构是什么?)
- [2. 为什么会有不同的数据结构?](#2. 为什么会有不同的数据结构?)
- 三、什么是算法?
- 四、数据结构和算法有什么关系?
-
- [1. 为什么两种方式会有差别?](#1. 为什么两种方式会有差别?)
- [2. 可以实际验证一下](#2. 可以实际验证一下)
- 五、为什么要学习数据结构与算法?
-
- [1. 从"能运行"到"运行得更好"](#1. 从“能运行”到“运行得更好”)
- [2. 不只是会用 `list` 和 `dict`](#2. 不只是会用
list和dict) - [3. 写代码之前先想清楚数据](#3. 写代码之前先想清楚数据)
- [4. 很多计算机知识都会回到这些基础](#4. 很多计算机知识都会回到这些基础)
- 六、总结
- 七、参考
一、什么是程序?
计算机科学中有一句非常经典的话:
程序 = 数据结构 + 算法
这句话也对应了 Niklaus Wirth 的经典著作《Algorithms + Data Structures = Programs》。
一个程序想要解决实际问题,通常离不开两个核心问题:
- 数据应该怎样组织和存储?
- 这些数据应该怎样被处理?
前者对应数据结构 ,后者对应算法。
可以简单理解为:
数据结构解决"数据怎么组织",算法解决"数据怎么处理"。
比如一个学生管理系统,需要保存学生的姓名、学号、成绩等信息,同时还需要完成查询、添加、删除、修改、排序等操作。
这里既涉及数据如何组织和存储,也涉及如何对这些数据进行处理。
真正写程序时,数据结构和算法往往是结合在一起的。
#mermaid-svg-dSJfXIF4EdueeFPc{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-dSJfXIF4EdueeFPc .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-dSJfXIF4EdueeFPc .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-dSJfXIF4EdueeFPc .error-icon{fill:#552222;}#mermaid-svg-dSJfXIF4EdueeFPc .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-dSJfXIF4EdueeFPc .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-dSJfXIF4EdueeFPc .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-dSJfXIF4EdueeFPc .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-dSJfXIF4EdueeFPc .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-dSJfXIF4EdueeFPc .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-dSJfXIF4EdueeFPc .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-dSJfXIF4EdueeFPc .marker{fill:#333333;stroke:#333333;}#mermaid-svg-dSJfXIF4EdueeFPc .marker.cross{stroke:#333333;}#mermaid-svg-dSJfXIF4EdueeFPc svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-dSJfXIF4EdueeFPc p{margin:0;}#mermaid-svg-dSJfXIF4EdueeFPc .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-dSJfXIF4EdueeFPc .cluster-label text{fill:#333;}#mermaid-svg-dSJfXIF4EdueeFPc .cluster-label span{color:#333;}#mermaid-svg-dSJfXIF4EdueeFPc .cluster-label span p{background-color:transparent;}#mermaid-svg-dSJfXIF4EdueeFPc .label text,#mermaid-svg-dSJfXIF4EdueeFPc span{fill:#333;color:#333;}#mermaid-svg-dSJfXIF4EdueeFPc .node rect,#mermaid-svg-dSJfXIF4EdueeFPc .node circle,#mermaid-svg-dSJfXIF4EdueeFPc .node ellipse,#mermaid-svg-dSJfXIF4EdueeFPc .node polygon,#mermaid-svg-dSJfXIF4EdueeFPc .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-dSJfXIF4EdueeFPc .rough-node .label text,#mermaid-svg-dSJfXIF4EdueeFPc .node .label text,#mermaid-svg-dSJfXIF4EdueeFPc .image-shape .label,#mermaid-svg-dSJfXIF4EdueeFPc .icon-shape .label{text-anchor:middle;}#mermaid-svg-dSJfXIF4EdueeFPc .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-dSJfXIF4EdueeFPc .rough-node .label,#mermaid-svg-dSJfXIF4EdueeFPc .node .label,#mermaid-svg-dSJfXIF4EdueeFPc .image-shape .label,#mermaid-svg-dSJfXIF4EdueeFPc .icon-shape .label{text-align:center;}#mermaid-svg-dSJfXIF4EdueeFPc .node.clickable{cursor:pointer;}#mermaid-svg-dSJfXIF4EdueeFPc .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-dSJfXIF4EdueeFPc .arrowheadPath{fill:#333333;}#mermaid-svg-dSJfXIF4EdueeFPc .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-dSJfXIF4EdueeFPc .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-dSJfXIF4EdueeFPc .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-dSJfXIF4EdueeFPc .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-dSJfXIF4EdueeFPc .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-dSJfXIF4EdueeFPc .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-dSJfXIF4EdueeFPc .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-dSJfXIF4EdueeFPc .cluster text{fill:#333;}#mermaid-svg-dSJfXIF4EdueeFPc .cluster span{color:#333;}#mermaid-svg-dSJfXIF4EdueeFPc div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-dSJfXIF4EdueeFPc .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-dSJfXIF4EdueeFPc rect.text{fill:none;stroke-width:0;}#mermaid-svg-dSJfXIF4EdueeFPc .icon-shape,#mermaid-svg-dSJfXIF4EdueeFPc .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-dSJfXIF4EdueeFPc .icon-shape p,#mermaid-svg-dSJfXIF4EdueeFPc .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-dSJfXIF4EdueeFPc .icon-shape .label rect,#mermaid-svg-dSJfXIF4EdueeFPc .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-dSJfXIF4EdueeFPc .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-dSJfXIF4EdueeFPc .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-dSJfXIF4EdueeFPc :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 程序
数据结构
算法
数据怎么组织
数据怎么处理
解决实际问题
二、什么是数据结构?
在理解数据结构之前,先来看什么是数据。
例如一个学生管理系统中:
text
姓名:张三
学号:20260001
年龄:20
成绩:90
姓名、学号、年龄、成绩,这些都属于数据。
当学生数量从几个人增加到几千、几万甚至更多时,仅仅把数据保存下来已经不够了,还需要考虑:
- 怎样组织这些学生信息?
- 怎样通过学号找到某个学生?
- 怎样添加或删除学生?
- 怎样修改学生信息?
- 怎样按照成绩进行排序?
这时候,数据的组织方式就开始变得重要。
1. 数据结构是什么?
数据结构是数据在计算机中的组织、存储以及数据之间关系的表示方式。
通俗一点说,就是研究:
数据应该怎么组织。
例如,可以使用 Python 的列表保存学生姓名:
python
students = ["张三", "李四", "王五"]
这些数据按照一定顺序组织在一起。
也可以通过学号组织学生信息:
python
students = {
"20260001": "张三",
"20260002": "李四",
"20260003": "王五"
}
虽然保存的仍然是学生信息,但组织方式已经不同。
数据怎样组织,会影响后续查找、插入、删除等操作的实现方式和效率。
2. 为什么会有不同的数据结构?
因为现实中的数据关系并不完全相同。
有些数据是按照顺序排列的,有些具有明显的层级关系,还有一些数据之间存在复杂的连接关系。
因此,计算机中形成了许多不同的数据结构,例如:
数组、链表、栈、队列、哈希表、树、堆、图等。
它们本质上都是在用不同的方式组织数据,以适应不同的问题和操作需求。
例如:
text
一组连续的数据 → 数组
先进先出的任务 → 队列
具有上下级关系的数据 → 树
相互连接的节点 → 图
这里真正需要关注的不是这些名字,而是:
不同的问题,需要的数据组织方式可能并不相同。
三、什么是算法?
有了数据以后,还需要对数据进行处理。
例如现在有一组数字:
python
nums = [5, 2, 9, 1, 7]
要求找出其中最大的数字。
可以这样做:
python
max_num = nums[0]
for num in nums:
if num > max_num:
max_num = num
print(max_num)
运行结果:
text
9
整个过程实际上就是:
text
先把第一个数字作为当前最大值
↓
依次与后面的数字比较
↓
如果发现更大的数字就替换
↓
继续比较直到结束
↓
得到最大值
这就是一种算法。
算法是解决某个问题的一系列明确步骤和方法。
比如:
- 查找一个数据;
- 对一组数字进行排序;
- 计算两个城市之间的最短路线;
- 判断一个字符串是否满足某种条件。
这些问题都需要相应的算法。
算法并不一定意味着复杂的数学公式。像前面的"依次比较并保留当前最大值",本身就是一种非常基础的算法。
真正值得关注的是:
为什么要按照这样的步骤解决问题?有没有更合适的方法?
四、数据结构和算法有什么关系?
数据结构和算法经常放在一起,是因为两者本身就有很强的联系。
数据怎么组织,会直接影响数据应该怎么处理。
假设现在有三个用户:
python
users = [
{"id": 1001, "name": "张三"},
{"id": 1002, "name": "李四"},
{"id": 1003, "name": "王五"}
]
现在需要找到 ID 为 1003 的用户。
一种直接的方法,是从第一个用户开始依次查找:
python
for user in users:
if user["id"] == 1003:
print(user)
数据很少时,这种方式没有什么问题。
但如果用户数量变成几十万甚至几百万,就需要开始考虑查找效率。
如果换一种方式组织数据:
python
users = {
1001: {"name": "张三"},
1002: {"name": "李四"},
1003: {"name": "王五"}
}
查找时可以直接通过 ID 获取:
python
print(users[1003])
同样是在完成"根据 ID 查找用户"这个任务,但数据的组织方式不同,处理方式和效率也随之发生变化。
1. 为什么两种方式会有差别?
列表中的数据是按顺序保存的。
如果不知道目标在哪,就可能需要:
text
第 1 个 → 不是
第 2 个 → 不是
第 3 个 → 不是
......
直到找到目标
假设一共有 n 条数据,最坏情况下可能需要检查接近 n 次。
这种查找通常记作:
text
O(n)
而 Python 的 dict 底层使用的是哈希表。
根据 key 查找时,并不是简单地从第一条数据开始逐个比较,而是会通过哈希值定位到相应位置。
在平均情况下,它的查找复杂度通常可以看作:
text
O(1)
简单对比如下:
| 数据组织方式 | 查找方法 | 平均查找复杂度 |
|---|---|---|
列表 list |
从前往后逐个比较 | O(n) |
字典 dict |
根据 key 进行哈希定位 | O(1) |
这里暂时不需要深入研究时间复杂度。
只需要知道:
O(n):数据越来越多,需要进行的操作通常也会随之增加;O(1):平均情况下,操作次数不会随着数据规模线性增长。
这也说明了一个很重要的问题:
选择什么样的数据结构,本身就可能影响程序的效率。
2. 可以实际验证一下
如果想直观看看这种差别,可以用 Python 的 timeit 做一个简单测试:
python
import timeit
users_list = [
{"id": i, "name": f"user{i}"}
for i in range(100000)
]
users_dict = {
i: {"name": f"user{i}"}
for i in range(100000)
}
target = 99999
def find_from_list():
for user in users_list:
if user["id"] == target:
return user
def find_from_dict():
return users_dict[target]
list_time = timeit.timeit(find_from_list, number=100)
dict_time = timeit.timeit(find_from_dict, number=100)
print("list:", list_time)
print("dict:", dict_time)
不同电脑、不同 Python 版本得到的具体数字会有差异,因此这里没有必要死记某个耗时结果。
更值得观察的是:
当数据规模逐渐增大时,逐个遍历列表的耗时会越来越明显,而按照 key 查询字典通常仍然能够保持较高的查找效率。
这就是"数据结构影响算法和程序效率"的一个非常直观的例子。
一个实际问题通常可以逐渐拆成:
#mermaid-svg-8Td4i0uWeqQJ4mLQ{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-8Td4i0uWeqQJ4mLQ .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-8Td4i0uWeqQJ4mLQ .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-8Td4i0uWeqQJ4mLQ .error-icon{fill:#552222;}#mermaid-svg-8Td4i0uWeqQJ4mLQ .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-8Td4i0uWeqQJ4mLQ .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-8Td4i0uWeqQJ4mLQ .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-8Td4i0uWeqQJ4mLQ .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-8Td4i0uWeqQJ4mLQ .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-8Td4i0uWeqQJ4mLQ .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-8Td4i0uWeqQJ4mLQ .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-8Td4i0uWeqQJ4mLQ .marker{fill:#333333;stroke:#333333;}#mermaid-svg-8Td4i0uWeqQJ4mLQ .marker.cross{stroke:#333333;}#mermaid-svg-8Td4i0uWeqQJ4mLQ svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-8Td4i0uWeqQJ4mLQ p{margin:0;}#mermaid-svg-8Td4i0uWeqQJ4mLQ .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-8Td4i0uWeqQJ4mLQ .cluster-label text{fill:#333;}#mermaid-svg-8Td4i0uWeqQJ4mLQ .cluster-label span{color:#333;}#mermaid-svg-8Td4i0uWeqQJ4mLQ .cluster-label span p{background-color:transparent;}#mermaid-svg-8Td4i0uWeqQJ4mLQ .label text,#mermaid-svg-8Td4i0uWeqQJ4mLQ span{fill:#333;color:#333;}#mermaid-svg-8Td4i0uWeqQJ4mLQ .node rect,#mermaid-svg-8Td4i0uWeqQJ4mLQ .node circle,#mermaid-svg-8Td4i0uWeqQJ4mLQ .node ellipse,#mermaid-svg-8Td4i0uWeqQJ4mLQ .node polygon,#mermaid-svg-8Td4i0uWeqQJ4mLQ .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-8Td4i0uWeqQJ4mLQ .rough-node .label text,#mermaid-svg-8Td4i0uWeqQJ4mLQ .node .label text,#mermaid-svg-8Td4i0uWeqQJ4mLQ .image-shape .label,#mermaid-svg-8Td4i0uWeqQJ4mLQ .icon-shape .label{text-anchor:middle;}#mermaid-svg-8Td4i0uWeqQJ4mLQ .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-8Td4i0uWeqQJ4mLQ .rough-node .label,#mermaid-svg-8Td4i0uWeqQJ4mLQ .node .label,#mermaid-svg-8Td4i0uWeqQJ4mLQ .image-shape .label,#mermaid-svg-8Td4i0uWeqQJ4mLQ .icon-shape .label{text-align:center;}#mermaid-svg-8Td4i0uWeqQJ4mLQ .node.clickable{cursor:pointer;}#mermaid-svg-8Td4i0uWeqQJ4mLQ .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-8Td4i0uWeqQJ4mLQ .arrowheadPath{fill:#333333;}#mermaid-svg-8Td4i0uWeqQJ4mLQ .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-8Td4i0uWeqQJ4mLQ .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-8Td4i0uWeqQJ4mLQ .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-8Td4i0uWeqQJ4mLQ .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-8Td4i0uWeqQJ4mLQ .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-8Td4i0uWeqQJ4mLQ .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-8Td4i0uWeqQJ4mLQ .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-8Td4i0uWeqQJ4mLQ .cluster text{fill:#333;}#mermaid-svg-8Td4i0uWeqQJ4mLQ .cluster span{color:#333;}#mermaid-svg-8Td4i0uWeqQJ4mLQ div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-8Td4i0uWeqQJ4mLQ .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-8Td4i0uWeqQJ4mLQ rect.text{fill:none;stroke-width:0;}#mermaid-svg-8Td4i0uWeqQJ4mLQ .icon-shape,#mermaid-svg-8Td4i0uWeqQJ4mLQ .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-8Td4i0uWeqQJ4mLQ .icon-shape p,#mermaid-svg-8Td4i0uWeqQJ4mLQ .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-8Td4i0uWeqQJ4mLQ .icon-shape .label rect,#mermaid-svg-8Td4i0uWeqQJ4mLQ .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-8Td4i0uWeqQJ4mLQ .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-8Td4i0uWeqQJ4mLQ .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-8Td4i0uWeqQJ4mLQ :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 现实问题
确定数据
选择数据结构
设计处理方法
算法
得到结果
选择什么样的数据结构,会影响算法怎么写;而需要完成什么操作,也会反过来影响数据结构的选择。
五、为什么要学习数据结构与算法?
平时写代码时,我们其实已经在不断使用数据结构和算法。
比如:
python
students = ["张三", "李四", "王五"]
或者:
python
student = {
"name": "张三",
"score": 90
}
甚至像:
python
for student in students:
print(student)
这些代码可能早就已经写过很多次。
很多时候,我们知道:
"这样写可以实现。"
却不一定清楚:
"为什么要这样写?"
为什么有时候使用 list,有时候更适合使用 dict?
为什么某些写法在十几条数据时几乎没有区别,到了几十万条数据以后差距却越来越明显?
为什么 set 经常用来判断一个元素是否存在?
这也是学习基础知识很重要的原因:
知其然,更要知其所以然。
学习数据结构与算法,不只是记住某种语法,而是逐渐从"知道怎么写",走向"理解为什么这样写"。
1. 从"能运行"到"运行得更好"
刚开始写程序时,最先考虑的通常是:
- 代码能不能运行?
- 结果是不是正确?
这是最基本的要求。
但随着程序规模和数据量增大,还需要继续考虑:
- 运行速度怎么样?
- 占用多少内存?
- 数据规模扩大以后还能不能正常工作?
- 有没有更合适的数据结构或算法?
两个程序可能都能得到正确答案,但实现方式并不一定相同。
一个可能需要进行上百万次操作,另一个可能只需要很少的操作。
所以:
代码能运行,只代表问题被解决了;怎么解决,则决定了程序能不能在更大的规模下继续工作。
2. 不只是会用 list 和 dict
平时使用 Python 时,我们可能已经非常熟悉:
python
nums = [1, 2, 3, 4]
或者:
python
student = {
"name": "张三",
"score": 90
}
这些写法本身并不难。
但继续往下看,就会出现更多问题:
- 为什么
dict根据 key 查找通常很快? - 为什么判断元素是否存在时经常使用
set? - 什么情况下适合使用
list? - 为什么有些操作换一种数据结构会更加合适?
当开始理解这些问题时,我们就不再只是调用 Python 提供好的工具,而是在逐渐理解这些工具背后的设计。
3. 写代码之前先想清楚数据
面对一个需求时,很容易直接进入:
"这个功能怎么写?"
但真正决定程序结构的,往往是更前面的问题。
比如要做一个任务管理系统,需要先考虑:
- 有哪些数据?
- 数据之间是什么关系?
- 哪些操作最频繁?
- 查询多还是修改多?
- 数据规模大不大?
- 应该怎样组织这些数据?
这些问题的答案不同,最后写出来的程序结构也可能完全不同。
写程序并不只是把语法拼起来。
更重要的是:
把现实中的问题抽象成计算机能够处理的数据,再设计合适的方法处理这些数据。
4. 很多计算机知识都会回到这些基础
很多常见技术背后,都能看到数据结构和算法。
例如:
text
函数调用 → 栈
任务调度 → 队列、堆
数据库索引 → 树
文件目录 → 树
地图导航 → 图
快速查找 → 哈希表
搜索 → 查找算法
比如文件目录本身就具有明显的层级关系:
text
D:
└── Code
├── project1
├── project2
└── project3
这种结构可以很自然地看成一棵树。
地图导航也是类似的道理。
城市、路口可以看成节点,道路可以看成节点之间的连接。
当整个道路网络被抽象成图以后,接下来才是在图上通过相应算法寻找路线。
数据结构和算法还会不断出现在操作系统、数据库、编译原理、计算机网络、搜索、人工智能等领域中。
越往后学习,越容易发现一些表面上完全不同的技术,最后都会重新遇到这些基础概念。
六、总结
程序解决问题时,通常既要考虑数据如何组织,也要考虑数据如何处理。
再次回到最开始的公式:
程序 = 数据结构 + 算法
其中,数据结构关注数据怎么组织 ,算法关注数据怎么处理、问题怎么解决。
平时写代码时,我们可能早就在使用各种数据结构和算法,只是更多停留在"这样写可以用"。
学习这些基础知识的意义,就是逐渐从:
我知道这样写能用。
走向:
我知道为什么这样写,也知道什么时候应该换一种写法。
面对新的问题时,可以多想一步:
text
有哪些数据?
↓
数据之间是什么关系?
↓
应该怎样组织这些数据?
↓
需要完成哪些操作?
↓
怎样处理更合理、更高效?
这也是后面继续学习数组、链表、栈、队列、哈希表、树、图以及各种算法时,可以一直带着的问题。