计算机的问题求解方法

官官方信息技术老师·22 页·深入(追求细节与边界)·0 次浏览·38 天前
计算思维问题拆解算法入门

计算机的问题求解方法

看完你能把一个真实问题一步步拆成计算机可执行的程序

按 空格/→ 演示下一步

问一句
1 / 22 页

全部页面点击任意一页,跳回舞台从这页播放

计算思维问题拆解算法入门

计算机的问题求解方法

看完你能把一个真实问题一步步拆成计算机可执行的程序

1第 1 页 · 计算机的问题求解方法

程序设计面向的问题

上一页说,计算机解题靠把问题拆成一步步执行。但不是所有问题都能这么拆——有些问题再快的机器也算不出来。那什么样的题才值得交给它?得连过三道关。

可计算
存在明确的求解步骤,而非“人类直觉”,如图灵可计算问题
可描述
输入输出和数据都能形式化,规则无歧义,比如“找最大数”
可自动化
步骤有限、机械可执行,机器无需理解含义就能逐步完成
给人下达做菜指令对应 →把问题交给计算机

菜谱写得足够明确,才能让完全不懂做菜的人照做成功

2第 2 页 · 程序设计面向的问题

求解路径总览

前面说了计算机擅长解决什么问题,但拿到一个问题,从想法到能跑的程序并不是一步到位的。就像做菜:先想吃什么、再定菜谱、写成步骤卡、最后下锅。这个过程拆开正好四步。

问题分析
搞清楚输入是什么、要输出什么、有哪些约束条件
算法设计
想出一条从输入走到输出的确定计算路径
算法表示
用流程图或伪代码把算法写下来,供人检查
程序实现
翻译成某种编程语言,让机器真正执行
做一道菜的流程对应 →问题求解四步

定吃什么对应问题分析,定菜谱对应算法设计,写步骤卡对应算法表示,下锅对应程序实现

3第 3 页 · 求解路径总览

什么是计算

前几页我们梳理了求解路径,但有个更根本的问题:计算机到底在做什么?你以为它只会算 3+4=7?其实按规则改动符号这件事,都是计算。

狭义计算
加减乘除等算术运算,是计算的最初形态
广义计算
一切按明确规则进行的符号变换与信息处理
规则与符号
计算的两个核心:有操作规则,有被处理的对象
边界所在
规则必须明确无歧义,模糊不清的事无法交给计算机
按菜谱做菜对应 →广义计算

菜谱的步骤对应规则,食材对应符号,成品就是输出

4第 4 页 · 什么是计算

冯·诺依曼结构与可计算性

上一页说「计算」是把输入变输出。可机器怎么知道下一步做什么?想想菜谱:步骤和食材写在同一张纸上,厨师照着逐条做——冯·诺依曼把这个思路搬进了计算机。

存储程序
指令和数据都以二进制形式存进同一个内存
指令也是数据
指令可被读取、修改、加载,与普通数据无异
自动按序执行
取指令→译码→执行,周而复始,无需人工干预
通用性
换程序即换任务,同一台机器能做任何可计算的问题
菜谱与食材同放一纸对应 →存储程序

菜谱上的步骤对应指令,食材对应数据,都在内存中

5第 5 页 · 冯·诺依曼结构与可计算性

计算模型的边界

从左往右读:任何问题先问能否给出算法,答案决定了它落在可计算或不可计算哪一侧。

图解渲染中…
b2:不存在任何算法能在有限步骤内解决c2:判定任意程序是否会停止的经典不可计算问题
6第 6 页 · 计算模型的边界

算法:解决问题的步骤

做红烧肉时菜谱会写:切块、焯水、加糖炒色、炖四十分钟——步骤有限、每步说得清、谁照着做都能执行。算法就是这种「照做就能解决」的步骤序列的正式名字。

有穷性
步骤必须有限,不能永远炒不完一道菜
确定性
每步含义唯一明确,不能写「适量加盐」
可行性
每步操作都能被真正执行,如「精确到无穷位」不行
有输出
至少产生一个结果,菜最终要端上桌
菜谱对应 →算法

菜谱的步骤对应算法操作,菜对应输出结果

7第 7 页 · 算法:解决问题的步骤

算法特征:有穷性与确定性

很多人把算法等同于菜谱,但菜谱在两个关键点上并不合格——这正是算法定义的边界所在。

菜谱
  • “炒至金黄”无判定标准,依赖厨师经验
  • “适量”“少许”,用量无法精确执行
  • 步骤可能失败收场,不保证产出结果
算法
  • 每步操作有唯一解释,任何执行者结果一致
  • 输入、每步规则完全明确,无模糊词
  • 对合法输入必定终止并输出确定结果
判断某流程是不是算法:步骤有歧义或可能不终止,就只是菜谱式流程;两者都满足,才是算法。
8第 8 页 · 算法特征:有穷性与确定性

算法特征:可行性、输入与输出

前两页我们确认了算法要「走得完、走得准」。但菜谱里若写「撒上一撮运气」,厨师照样卡壳——每一步都得真做得了。同时菜谱要食材、要端出成品,算法也讲究进出。

可行性
每一步都能由基本操作在实际可完成,如除法可化为减法逼近
输入
零个或多个外界给定的量;如求阶乘可不需输入
输出
至少一个产生结果,与输入有确定关系;无输出的步骤序列无意义
做一道菜对应 →算法三特征

菜谱步骤须可操作对应可行性;食材对应输入;端出的菜对应输出

9第 9 页 · 算法特征:可行性、输入与输出

自测:这算算法吗

点击作答

这段“泡茶步骤”不满足算法的哪些特征?

10第 10 页 · 自测:这算算法吗

自然语言表示

前面说算法必须确定性、无歧义。那最顺手的方式——直接用中文把步骤写下来行不行?试试「找出这组数里最大的那个」,每个人理解一样吗?

最直观
像日常说话,想到哪写到哪,零门槛
歧义难除
「最大的」指数值还是位置?并列怎么办?
无法执行
计算机不能直接理解,仍需人翻译成代码
口头传话对应 →自然语言算法

传话每转一次意思就偏一点,算法容不得这种偏差

11第 11 页 · 自然语言表示

流程图表示

用流程图的三种符号画出三种控制结构:椭圆是起点终点,菱形是判断分支,箭头是流程线,顺着箭头读执行路径。

图解渲染中…
c1:菱形判断框:一个入口两个出口,对应分支结构c2:判断框回指语句组,构成循环结构s3:矩形处理框:具体操作步骤
12第 12 页 · 流程图表示

伪代码与 N-S 图

自然语言描述算法容易有歧义,流程图画起来又慢又占地方。有没有折中方案?工程师用了一套接近代码、又不受具体语言语法约束的书写方式——伪代码,配合 N-S 图,让算法一步步逼近真正的程序。

伪代码
像代码但不限语法,只保留控制结构和关键操作
N-S 图
去掉箭头的流程图,用矩形嵌套表示三种基本结构
结构化三件套
只用顺序、分支、循环三种结构组合搭建算法
逐步逼近代码
写清逻辑后,翻译成任何一门语言都容易
建筑设计草图对应 →伪代码

草图画结构与布局,不必标注每种材料;代码才是施工图

13第 13 页 · 伪代码与 N-S 图

从伪代码到 C 程序

c

同一算法的三级表示:伪代码如何逐行落地为可编译运行的 C 程序。

代码高亮加载中…

伪代码的每一步都能在 C 中找到唯一对应:变量声明补上类型,循环与累加原样落地,最后用格式化输出得到 5050。

14第 14 页 · 从伪代码到 C 程序

为什么算法要优化

同一道题,你写的程序 1 秒出结果,同学的跑了半小时还没停。都能得到答案,差别在哪?前面我们确认了算法必须正确,现在看另一个维度:算得对,和算得好,是两回事。

结果对≠算法好
正确只是底线,两条正确路径的效率可能差百万倍
时间代价
同一问题,不同算法运行时间可从毫秒到数年
空间代价
算法占用的内存差异同样悬殊,资源是硬约束
优化动机
数据规模一大,劣算法彻底不可用,必须换思路
两条回家的路对应 →不同算法

都能到家,但堵车的绕远路对应效率低下的算法

n=106时:n2步≈11.6 天nlog⁡n步≈0.02 秒n=10^6 时:n^2 步 \approx 11.6\,\text{天}\quad n\log n 步 \approx 0.02\,\text{秒}
15第 15 页 · 为什么算法要优化

优化实例:求和与查找

同一问题常有多种解法,朴素解法正确但慢;改进解法好在哪、边界在哪,值得逐项对照。

朴素解法
  • 求和:逐项累加 1 到 n
  • 查找:从头到尾逐个比对
  • 时间随规模线性增长 O(n)
改进解法
  • 求和:用公式 n(n+1)/2 一次算出
  • 查找:有序数据折半,每次砍一半
  • 对数级 O(log n),常数级 O(1)
数据无序且规模小选朴素;数据有序或规模大、可推导公式时选改进。
16第 16 页 · 优化实例:求和与查找

优化的思路

算法优化不是一步登天,而是沿固定路径逐级推进。

1
先正确
用直观方法做出能算对结果的版本,作为基线
2
再简化
审视逻辑,去掉重复与冗余,让结构更清晰
3
再提效
换数据组织或策略,降低时间与空间开销
4
验证比较
测试边界情况,量化改进幅度,确认没有引入新问题
17第 17 页 · 优化的思路

自顶向下逐步求精

上一页我们优化了求和与查找,靠的是换思路。可问题一大,思路就不够用了——做一桌年夜饭没人会同时炒所有菜,先定菜单,再分到每道菜,这正是自顶向下的做法。

分解
把大问题拆成若干可独立解决的子问题
模块化
每个子问题对应一个功能模块,接口清晰
逐步求精
对每个模块继续拆,直到能用语句直接实现
验证与组装
先分别确认各模块正确,再组合成完整解
筹备年夜饭对应 →自顶向下逐步求精

菜单对应总目标,每道菜对应子模块,具体步骤对应代码

18第 18 页 · 自顶向下逐步求精

三种基本控制结构

图中有三条支路:直线是顺序,菱形分岔是选择,带回边的路径是循环,箭头汇合处表示任何算法都能由它们拼成。

图解渲染中…
a1:顺序:语句依次执行,A做完才做Bm1:选择:按条件真假走不同分支a5:循环:回边让流程重复,直到条件不成立h1:三种结构都只有单一入口和单一出口
19第 19 页 · 三种基本控制结构

模块化与 C 语言落地

c

看一个自顶向下设计的完整落地:求和任务拆成函数,每个函数负责一件事。

代码高亮加载中…

sum、report 各自封装一步求精,main 是顶层调度——这就是自顶向下在 C 里的样子:层层分解成函数,main 只管调用。

20第 20 页 · 模块化与 C 语言落地

从问题到程序的完整闭环

  • ✓问题先变成可计算的问题,才轮得到计算机出场
  • ✓算法是核心:有穷、确定、可行,缺一不可
  • ✓同一问题解法差异巨大,优化比写出答案更重要
  • ✓表示只是桥梁:自然语言到 C,语义不能走样
  • ✓自顶向下求精加模块化,复杂度被分而治之
延伸主题:算法复杂度与大 O 分析数据结构如何支撑算法不可计算问题与停机定理
21第 21 页 · 从问题到程序的完整闭环

课后思考

先合上讲义自己想几分钟,再看参考答案,核对思路方向。

1有穷性要求算法必须终止,那操作系统里的死循环监控程序,算不算算法?为什么?

参考答案从定义看它不满足有穷性,更接近'服务过程'而非'一次求解'。想一层:如果把'处理一次事件'拆成单轮,每一轮是否有穷、确定?边界在于我们给算法划的'一次求解'范围。

2把'自顶向下逐步求精+模块化'用到你正在做的课程作业或项目上,第一步会怎么拆?

参考答案先别想代码,先用一句话写出最终目标,再问'它依赖哪几个子结果'。对照第 20 页的闭环:问题→算法→程序,拆到每个子问题都能用三种基本结构描述为止。

3图灵机告诉我们可计算的边界,那'不可计算'是不是意味着永远无解?谈谈你的理解。

参考答案不可计算指'不存在算法一步步机械求解',不等于无解——有些问题靠人的洞察、数学证明或限定条件后可解。思考:可计算性是'方法的边界',不是'答案的边界'。

22第 22 页 · 课后思考