流程控制之分支结构教学讲义


1. 分支结构简介

1.1 什么是分支结构

分支结构(Selection Structure):根据某个条件是否成立(真/假),决定程序执行哪一段代码。它使得程序能够根据不同的情况做出不同的反应。

现实世界充满了选择:“如果下雨,就带伞;否则不带。”程序中的分支结构就是用来实现这种“如果…否则…”的逻辑。

图示:双分支执行流程

           ┌─────────────┐
           │  判断条件    │
           └──────┬──────┘
                  │
         ┌────────┴────────┐
         │ 真(true)        │ 假(false)
         ▼                 ▼
   ┌───────────┐     ┌───────────┐
   │ 语句块A   │     │ 语句块B   │
   └─────┬─────┘     └─────┬─────┘
         └────────┬────────┘
                  ▼
           ┌─────────────┐
           │   继续执行   │
           └─────────────┘

1.2 为什么需要分支结构

  • 实现逻辑判断:让程序能处理多种输入情况(如判断成绩是否及格)。
  • 增强程序鲁棒性:检测错误输入并给出提示(如除数为零)。
  • 构建复杂算法:任何非线性的算法(如排序、查找、游戏AI)都离不开分支。

没有分支结构的程序只能“一条路走到黑”,无法应对真实世界的变化。

2. 分支结构的类型

C++ 提供了多种分支语句,适用于不同的场景。

2.1 单分支:if 语句

格式:如果条件成立,就执行某段代码;否则跳过。

if (条件表达式) {
    // 条件为真时执行的语句块
}

示例:交换两个数,使 a 不大于 b。

if (a > b) {
    swap(a, b);   // 如果 a > b,交换它们的值
}
// 执行后 a <= b

注意:即使语句块只有一条语句,也建议加上花括号 {},避免后续添加语句时出错。

2.2 双分支:if-else 语句

格式:如果条件成立,执行语句块1;否则执行语句块2。

if (条件表达式) {
    // 条件为真时执行
} else {
    // 条件为假时执行
}

示例:输出两个数中较小的那个。

if (a < b) {
    cout << a << endl;
} else {
    cout << b << endl;
}

2.3 多分支:if-else if-else 结构

格式:从上到下依次判断多个条件,执行第一个满足条件的语句块。

if (条件1) {
    // 条件1为真
} else if (条件2) {
    // 条件1为假且条件2为真
} else if (条件3) {
    // 条件1、2为假且条件3为真
} else {
    // 所有条件均为假
}

示例:根据分数评定等级(A~E)。

if (score >= 90) {
    cout << "A" << endl;
} else if (score >= 80) {
    cout << "B" << endl;
} else if (score >= 70) {
    cout << "C" << endl;
} else if (score >= 60) {
    cout << "D" << endl;
} else {
    cout << "E" << endl;
}

关键点:else if 会逐层排除前面的条件,因此条件顺序很重要。例如,score >= 80 的分支不会包含 score >= 90 的情况,因为 >=90 已经在第一个分支中被处理了。

2.4 嵌套分支

在 if 或 else 的代码块内部再使用另一个 if 语句,形成多层判断。

示例:求三个数中的最大值(嵌套写法)。

int maxNum;
if (a > b) {
    if (a > c) {
        maxNum = a;
    } else {
        maxNum = c;
    }
} else {
    if (b > c) {
        maxNum = b;
    } else {
        maxNum = c;
    }
}
cout << maxNum << endl;

嵌套不宜过深(一般不超过3层),否则可读性下降,可考虑用逻辑运算符简化。

2.5 多分支开关:switch 语句

适用场景:基于单个整型表达式的多个等值判断(如菜单选择、星期几)。

switch (表达式) {
    case 常量1:
        语句块1;
        break;
    case 常量2:
        语句块2;
        break;
    // ... 更多 case
    default:
        默认语句块;
        break;
}

示例:输入数字1~7,输出对应的星期英文。

switch (n) {
    case 1: cout << "Monday" << endl; break;
    case 2: cout << "Tuesday" << endl; break;
    case 3: cout << "Wednesday" << endl; break;
    case 4: cout << "Thursday" << endl; break;
    case 5: cout << "Friday" << endl; break;
    case 6: cout << "Saturday" << endl; break;
    case 7: cout << "Sunday" << endl; break;
    default: cout << "Error" << endl; break;
}

注意:

  • 表达式只能是整型、字符型、布尔型、枚举型(不能是浮点型或字符串)。
  • 每个 case 末尾通常要加 break,否则会发生“穿透”(继续执行下一个 case 的代码)。
  • default 分支可选,用于处理所有未列出的情况。

2.6 条件运算符 ? :

一种简洁的三目运算符,用于简单的二选一赋值。

条件表达式 ? 值1 : 值2

示例:求 a 和 b 的最大值。

int maxNum = (a > b) ? a : b;

注意:条件运算符不能代替复杂的 if-else,只适合简单场景。

3. 经典问题示例

3.1 BMI 体重指数判定

double bmi;  // 假设已计算好
if (bmi < 18.5) {
    cout << "偏瘦" << endl;
} else if (bmi < 24) {
    cout << "正常" << endl;
} else if (bmi < 28) {
    cout << "超重" << endl;
} else {
    cout << "肥胖" << endl;
}

3.2 闰年判断(多种写法)

解法一:单分支(最简洁)

if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) {
    cout << "Yes" << endl;
} else {
    cout << "No" << endl;
}

解法二:多分支(逐层排除)

bool leap;
if (year % 100 == 0) {          // 世纪年
    if (year % 400 == 0) leap = true;
    else leap = false;
} else {                        // 普通年
    if (year % 4 == 0) leap = true;
    else leap = false;
}
cout << (leap ? "Yes" : "No") << endl;

解法三:嵌套分支(与解法二本质相同)

bool leap = false;
if (year % 4 == 0) {
    if (year % 100 == 0) {
        if (year % 400 == 0) leap = true;
    } else {
        leap = true;
    }
}
cout << (leap ? "Yes" : "No") << endl;

推荐:竞赛中通常使用最简洁的逻辑表达式,因为它清晰且高效。

4. 课堂例题

例题1:成绩等级评定

题目描述

输入一个整数成绩 score(0 ≤ score ≤ 100),输出对应的等级:

  • 90~100:A
  • 80~89:B
  • 70~79:C
  • 60~69:D
  • 0~59:E

输入:一个整数。 输出:一个大写字母。

思路解析

本题属于典型的多分支结构。可以使用 if-else if 逐段判断,注意区间端点的处理(建议使用 >= 和 < 结合,避免重复判断)。也可以使用 switch,但 switch 处理区间较麻烦,故选用 else-if。

代码实现

#include <bits/stdc++.h>
using namespace std;

int main() {
    int score;
    cin >> score;
    
    if (score >= 90) {
        cout << "A" << endl;
    } else if (score >= 80) {
        cout << "B" << endl;
    } else if (score >= 70) {
        cout << "C" << endl;
    } else if (score >= 60) {
        cout << "D" << endl;
    } else {
        cout << "E" << endl;
    }
    return 0;
}

教练提示:为什么不用 if (90 <= score <= 100) ?因为 C++ 不支持连续比较,必须写成 score >= 90 && score <= 100。但在 else-if 结构中,由于前面已经排除了 >=90 的情况,else if (score >= 80) 自然对应 80~89,无需再写上限。

例题2:闰年判断

题目描述

输入一个年份 year(1 ≤ year ≤ 9999),判断是否为闰年。输出 "YES" 或 "NO"。

闰年规则:

  • 能被4整除但不能被100整除的年份是闰年;
  • 能被400整除的年份也是闰年。

思路解析

直接使用逻辑运算符组合两个条件即可。注意运算符优先级:% > ==、!= > && > ||。为清晰可加括号。

代码实现

#include <bits/stdc++.h>
using namespace std;

int main() {
    int year;
    cin >> year;
    
    if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) {
        cout << "YES" << endl;
    } else {
        cout << "NO" << endl;
    }
    return 0;
}

常见错误:写成 year % 4 == 0 && year % 100 != 0 && year % 400 == 0,这永远为假,因为一个数不可能同时 %100 != 0 且 %400 == 0。正确用 || 连接。

例题3:三个数排序(输出升序)

题目描述

输入三个互不相等的整数 a, b, c,将它们按从小到大顺序输出,中间用空格隔开。

输入:一行三个整数。 输出:一行三个整数,升序排列。

思路解析

本题考察分支结构的综合运用。有多种解法:

  1. 枚举所有大小关系(6种情况),用 if-else if 写出。
  2. 通过比较和交换:先保证 a <= b,再保证 a <= c(此时 a 最小),最后保证 b <= c。这种方法代码简洁,也使用了分支。

我们采用第二种方法(交换法),便于理解。

代码实现

#include <bits/stdc++.h>
using namespace std;

int main() {
    int a, b, c;
    cin >> a >> b >> c;
    
    // 让 a 成为 a 和 b 中较小的
    if (a > b) swap(a, b);
    // 让 a 成为 a 和 c 中较小的(此时 a 是最小值)
    if (a > c) swap(a, c);
    // 此时 a 已最小,只需保证 b <= c
    if (b > c) swap(b, c);
    
    cout << a << " " << b << " " << c << endl;
    return 0;
}

思考:如果题目要求不改变原变量(即不能交换),则必须用枚举法或临时变量记录结果。

5. 课后练习

以下题目建议在洛谷(luogu.com.cn)上完成,涵盖分支结构的各种应用。

序号 题目名称 链接 知识点
1 【深基3.例2】数的性质 P5710 条件组合(与、或、非)
2 【深基3.例3】闰年判断 P5711 闰年规则
3 【深基3.例4】Apples P5712 单分支与输出
4 【深基3.例5】肥胖问题 P5714 BMI 计算与多分支
5 【深基3.例8】三位数排序 P5715 三个数排序(分支实现)
6 【深基3.例9】月份天数 P5716 多分支 + 闰年
7 买铅笔 P1909 多分支求最小值
8 小玉家的电费 P1422 分段计费(多分支)
9 不高兴的津津 P1085 分支结构 + 比较
10 三角形分类 P5717 复杂条件组合

建议:先独立完成,再对照题解优化。尤其注意边界条件(如 >= 和 > 的区别)。

6. 总结

分支类型 语法关键词 适用场景 注意事项
单分支 if 某个条件下才执行的代码 即使单语句也建议加 {}
双分支 if-else 二选一 不要忘记 else 后的 {}
多分支 if-else if-else 基于范围的多个互斥条件 注意条件顺序,先处理范围小的
嵌套分支 if 内部再写 if 需要多层判断时 嵌套不宜过深,可改用逻辑运算符
开关分支 switch-case-break 基于整型常量值的多分支 不要忘记 break,否则会穿透
条件运算符 ? : 简单的二选一赋值 不要过度使用,可读性更重要

核心技巧:

  • 条件表达式要写完整,注意 == 与 = 的区别(常犯错误:if (a = 5) 是赋值,永远为真)。
  • 浮点数比较不要直接用 ==,改用 fabs(a - b) < 1e-9。
  • else 总是与最近的未匹配的 if 结合(注意花括号可以改变配对)。

教练寄语:分支结构是程序拥有“智能”的第一步。请务必多动手编写代码,尤其是课堂例题和课后练习。当你能够熟练地用分支解决生活中的判断问题时(比如根据天气决定穿什么),你就真正掌握了它。

参考资料

  • 【书籍】《信息学奥赛一本通》第2章:顺序结构与分支结构
  • 【书籍】《C++ Primer Plus》第6章:分支语句和逻辑运算符
  • 【在线资源】OI Wiki - 分支结构