什么是算法?
算法是解决一个问题所采取的方法和步骤的集合
生活中的算法
🍳
做菜的步骤
洗菜 → 切菜 → 热锅 → 炒菜 → 出锅
做菜就是一个算法:有明确的步骤(有穷性),每步操作确定(确定性),有输入(食材),有输出(菜品),每步可行(有效性)。
🗺️
查字典
翻到近似页 → 对比首字母 → 前翻或后翻 → 找到目标
查字典本质是"二分查找"算法的原型——每次将搜索范围缩小一半,直到找到目标。
📱
手机导航
输入起点 → 输入终点 → 选择路线 → 开始导航
导航软件内部使用图论算法(如Dijkstra最短路径算法),在数百万条道路中找到最优路线。
算法的定义
广义地说,为解决一个问题而采取的方法和步骤,就称为"算法"。
对于同一个问题,可以有多种算法,但算法有优劣之分。
例如,求1+2+…+100:
❌ 方法1:逐项相加
1+2+3+4+…+99+100
需要做99次加法
✅ 方法2:高斯求和
(1+100)×100/2 = 5050
只需1次计算!
选择合适的算法是程序设计的核心——好的算法让程序更快、更省资源。
简单算法举例
5个经典算法,可交互式分步执行,直观理解算法过程
1 求 1×2×3×4×5(阶乘)
步骤0: 设 t = 1
步骤1: 设 i = 2
步骤2: 如果 i ≤ n, 执行步骤3; 否则转步骤5
步骤3: t = t × i
步骤4: i = i + 1, 转步骤2
步骤5: 输出 t, 算法结束
2 判断一个正整数是否为素数
步骤1: 输入 n
步骤2: 设 i = 2
步骤3: 如果 i < n, 执行步骤4; 否则转步骤6
步骤4: 如果 n mod i = 0, 输出"不是素数", 结束
步骤5: i = i + 1, 转步骤3
步骤6: 输出"是素数", 结束
4 求 1 - 1/2 + 1/3 - 1/4 + … + 1/99 - 1/100
步骤1: sign = 1, sum = 1, i = 2
步骤2: sign = (-1) × sign
步骤3: sum = sum + sign × (1/i)
步骤4: i = i + 1
步骤5: 如果 i ≤ 100, 转步骤2
步骤6: 输出 sum, 结束
5 求最大公约数(辗转相除法)
步骤1: 输入 m, n
步骤2: r = m mod n
步骤3: 如果 r ≠ 0, m=n, n=r, 转步骤2
步骤4: 输出 n (最大公约数), 结束
算法的特性
一个有效的算法必须同时具备以下5个特性——点击卡片翻转查看详解
算法必须在执行有限步骤之后终止,不能无限循环。每一步都在有限时间内完成。
❌ 反例:死循环不是算法
算法中的每一步必须有确定的含义,不能有二义性。相同输入必须得到相同输出。
❌ 反例:"加一点盐"不精确
算法可以有0个或多个输入。有些算法不需要外部输入(如打印固定字符串),有些需要多个参数。
例:printf("Hello") 无输入
算法必须至少有一个输出。没有输出的算法毫无意义——输出是算法对问题的解答。
输出可以是打印、返回值、文件等
算法中的每一步都必须是可以执行的,每步操作在现有条件下都能实现,且得到确定结果。
❌ 反例:除以0不是有效操作
怎样表示一个算法
6种表示方法对比——点击切换查看不同表示方式
用自然语言表示算法
自然语言就是人们日常使用的语言(如中文、英文)。用自然语言表示算法通俗易懂,但文字冗长,容易出现歧义。
例:求1×2×3×4×5
S1:使 t = 1
S2:使 i = 2
S3:使 t × i,乘积仍放在变量 t 中
S4:使 i 的值加1,即 i = i + 1
S5:如果 i ≤ 5,返回重新执行S3;否则算法结束,t中的值就是5!
⚠️ 缺点:自然语言容易有歧义,如"使 t × i"表述不精确;对复杂算法描述冗长
用流程图表示算法
流程图是用一组图形符号来表示算法的直观方法。各符号含义如下:
求 1×2×3×…×n 的流程图
用N-S流程图表示算法
1973年,美国学者I. Nassi和B. Shneiderman提出了一种新的流程图形式——完全去掉流程线,所有算法写在一个矩形框内。又称盒图。
求 1×2×3×…×n 的N-S图
✅ 优点:N-S图没有流程线,不会出现随意跳转,保证了程序的结构化;比传统流程图更紧凑
用伪代码表示算法
伪代码是用介于自然语言和计算机语言之间的文字和符号来描述算法。它结构清晰、代码简单、可读性好。
BEGIN // 算法开始
t ← 1 // 初始化t
i ← 2 // 初始化i
WHILE i ≤ n DO // 当i≤n时循环
t ← t × i // 累乘
i ← i + 1 // i递增
END WHILE
PRINT t // 输出结果
END // 算法结束
💡 伪代码特点:用 ← 表示赋值,用 WHILE/IF 等关键字控制流程,既像自然语言易懂,又像代码严谨
用C语言表示算法
最终,算法要用计算机语言编写成程序才能在计算机上执行。以下是求阶乘的C语言程序:
#include <stdio.h>
int main()
{
int i, n;
long t = 1; // 累乘器初始化为1
printf("请输入n: ");
scanf("%d", &n);
for (i = 2; i <= n; i++)
t = t * i; // 累乘
printf("%d! = %ld\n", n, t);
return 0;
}
六种表示方法对比
| 表示方法 |
直观性 |
精确性 |
可执行 |
适用场景 |
| 自然语言 |
⭐⭐⭐ |
⭐ |
❌ |
日常交流、初步思考 |
| 流程图 |
⭐⭐⭐⭐ |
⭐⭐⭐ |
❌ |
教学展示、算法设计 |
| N-S图 |
⭐⭐⭐ |
⭐⭐⭐⭐ |
❌ |
结构化程序设计 |
| 伪代码 |
⭐⭐⭐ |
⭐⭐⭐⭐ |
❌ |
算法设计、学术交流 |
| C语言 |
⭐⭐ |
⭐⭐⭐⭐⭐ |
✅ |
实际编程、程序运行 |
三种基本结构
1966年,Bohra和Jacopini证明了:任何算法都可以由顺序、选择、循环三种基本结构组成
顺序结构
顺序结构是最简单的程序结构——各操作步骤按照书写顺序依次执行,不发生跳转。
顺序结构流程图
选择结构
选择结构根据条件判断的结果,选择执行不同的操作。又称分支结构。
IF 条件P THEN
执行语句A // 条件为真
ELSE
执行语句B // 条件为假
END IF
选择结构流程图
循环结构
循环结构又称重复结构,在条件满足时反复执行某段操作。分为当型循环(WHILE)和直到型循环(UNTIL)两种。
当型循环 (WHILE)
WHILE P DO
循环体A
END WHILE
先判断条件P,为真才执行循环体
直到型循环 (UNTIL)
先执行循环体,直到条件P为真时退出
当型循环流程图
结构化程序设计
结构化程序设计强调:
三种基本结构组成的算法,可以解决任何复杂问题——这就是结构化程序设计的核心思想。