详细介绍:C++基础知识编程第十六课
C++ 编程第十六课:一维数组可拓展知识点(找最值、排序与查找)

课程导航
- 为什么要学数组拓展操作? (从 “基础遍历” 到 “实用处理” 的升级)
- 数组找最值:找出最大 / 最小值 (核心逻辑与实战案例)
- ⚡ 数组简单排序:冒泡排序与选择排序 (入门级排序算法,易懂好上手)
- 数组按值查找:找到元素对应的下标 (精确查找与模糊判断)
- 综合案例:结合多操作处理数组数据 (解决复杂实际问题)
- ⚠️ 拓展操作常见错误 (避坑指南,避免逻辑漏洞)
- 下节预告:do-while 循环详解(先执行后判断的循环新方式)
1. 为什么要学数组拓展操作?—— 从 “能用” 到 “好用”
之前我们学会了数组的遍历和动态赋值,能实现 “存储数据” 和 “逐个访问数据”,但实际场景中,我们需要对数组数据做更多 “深度处理”:
- 统计学生成绩时,需要 “找出最高分” 来确定满分人数;
- 整理商品价格时,需要 “按价格从低到高排序”,方便用户查看;
- 管理员工编号时,需要 “根据编号查找对应员工的信息”。
这些场景都需要数组的 “拓展操作”—— 找最值、排序、查找。学会这些操作,才能让数组从 “单纯的存储容器” 变成 “能解决实际问题的工具”,真正发挥数组的价值。
2. 数组找最值:找出最大 / 最小值
数组找最值的核心逻辑是 “假设一个初始最值,再遍历数组逐个对比更新”,就像 “选班长时,先暂定一个候选人,再和其他人对比,更优秀的人成为新候选人”。
(1)核心步骤(以找最大值为例)
- 假设初始最大值:把数组第一个元素(arr[0])当作初始最大值(maxVal);
- 遍历数组对比:从第二个元素(arr[1])开始,逐个和maxVal对比;
- 更新最大值:如果当前元素比maxVal大,就把maxVal更新为当前元素;
- 遍历结束:maxVal就是数组的最大值。
找最小值的逻辑完全相同,只是初始值设为arr[0],对比时找 “更小的元素”。
(2)代码实现:找数组的最大值和最小值
需求:定义一个 int 数组,找出数组中的最大值和最小值,并输出。
#include
using namespace std;
int main() {
int numbers[] = {15, 7, 22, 9, 30, 5};
int length = sizeof(numbers) / sizeof(int);
// 1. 假设初始最值(数组第一个元素)
int maxVal = numbers[0];
int minVal = numbers[0];
// 2. 遍历数组(从第二个元素开始,下标1)
for (int i = 1; i < length; i++) {
// 更新最大值
if (numbers[i] > maxVal) {
maxVal = numbers[i];
}
// 更新最小值
if (numbers[i] < minVal) {
minVal = numbers[i];
}
}
// 3. 输出结果
cout << "数组中的最大值:" << maxVal << endl; // 输出30
cout << "数组中的最小值:" << minVal << endl; // 输出5
return 0;
}
(3)实战案例:结合动态赋值找最值
需求:让用户输入 8 个整数,动态存入数组后,找出其中的最大值。
#include
using namespace std;
int main() {
const int SIZE = 8;
int arr[SIZE];
// 1. 动态赋值:用户输入8个整数
cout << "请输入8个整数:" << endl;
for (int i = 0; i < SIZE; i++) {
cout << "第" << (i + 1) << "个整数:";
cin >> arr[i];
}
// 2. 找最大值
int maxVal = arr[0];
for (int i = 1; i < SIZE; i++) {
if (arr[i] > maxVal) {
maxVal = arr[i];
}
}
cout << "你输入的8个整数中,最大值是:" << maxVal << endl;
return 0;
}
运行场景:
请输入8个整数:
第1个整数:12
第2个整数:45
第3个整数:23
第4个整数:56
第5个整数:7
第6个整数:34
第7个整数:67
第8个整数:28
你输入的8个整数中,最大值是:67
3. ⚡ 数组简单排序:冒泡排序与选择排序
排序是 “将数组元素按一定顺序(从小到大 / 从大到小)重新排列”,是数组最常用的操作之一。这里我们讲解两种入门级排序算法:冒泡排序和选择排序,逻辑简单,适合新手掌握。
(1)冒泡排序:“相邻元素对比,大的往后沉”
核心逻辑:像 “水泡从水底往上冒” 一样,每次遍历数组时,让相邻的两个元素对比,把较大的元素 “往后推”,遍历多次后,最大的元素会逐渐 “沉” 到数组末尾,最终实现排序。
代码实现:冒泡排序(从小到大)
#include
using namespace std;
int main() {
int scores[] = {85, 72, 93, 68, 98, 88};
int length = sizeof(scores) / sizeof(int);
// 冒泡排序核心:外层循环控制“排序轮次”,内层循环控制“每轮对比次数”
for (int i = 0; i < length - 1; i++) { // 轮次:length个元素需要length-1轮
for (int j = 0; j < length - 1 - i; j++) { // 每轮对比次数:轮次越多,对比次数越少
// 相邻元素对比,前大后小则交换(从小到大排序)
if (scores[j] > scores[j + 1]) {
// 交换两个元素的值(用临时变量temp过渡)
int temp = scores[j];
scores[j] = scores[j + 1];
scores[j + 1] = temp;
}
}
}
// 输出排序后的数组
cout << "冒泡排序后(从小到大):";
for (int i = 0; i < length; i++) {
cout << scores[i] << " ";
}
return 0;
}
运行结果:
冒泡排序后(从小到大):68 72 85 88 93 98
(2)选择排序:“找最小元素,放到最前面”
核心逻辑:每次遍历数组时,找到 “未排序部分的最小值”,把它和 “未排序部分的第一个元素” 交换,逐渐将最小值 “选” 到数组前面,最终实现排序。
代码实现:选择排序(从小到大)
#include
using namespace std;
int main() {
int prices[] = {29, 58, 15, 36, 42};
int length = sizeof(prices) / sizeof(int);
// 选择排序核心:外层循环控制“未排序部分的起始位置”
for (int i = 0; i < length - 1; i++) {
// 1. 假设未排序部分的第一个元素是最小值,记录其下标
int minIndex = i;
// 2. 遍历未排序部分,找到真正的最小值下标
for (int j = i + 1; j < length; j++) {
if (prices[j] < prices[minIndex]) {
minIndex = j; // 更新最小值下标
}
}
// 3. 把最小值和未排序部分的第一个元素交换
if (minIndex != i) { // 最小值不是当前元素时才交换
int temp = prices[i];
prices[i] = prices[minIndex];
prices[minIndex] = temp;
}
}
// 输出排序后的数组
cout << "选择排序后(从小到大):";
for (int i = 0; i < length; i++) {
cout << prices[i] << " ";
}
return 0;
}
运行结果:
选择排序后(从小到大):15 29 36 42 58
4. 数组按值查找:找到元素对应的下标
按值查找是 “根据给定的目标值,在数组中找到对应的元素,并返回它的下标”,就像 “根据名字在通讯录中找电话号码”。如果数组中有多个相同的目标值,通常返回 “第一个匹配元素的下标”。
(1)核心步骤
- 遍历数组:逐个访问数组元素;
- 对比目标值:判断当前元素是否等于目标值;
- 返回下标:找到匹配元素,立即返回其下标;
- 查找失败:遍历结束仍未找到,返回一个特殊值(比如 - 1,表示 “不存在”)。
(2)代码实现:按值查找元素下标
需求:定义一个 int 数组,让用户输入目标值,查找该值在数组中的下标(若不存在,提示 “未找到”)。
#include
using namespace std;
int main() {
int ids[] = {101, 102, 103, 104, 105};
int length = sizeof(ids) / sizeof(int);
int target, index = -1; // index初始为-1(表示未找到)
// 1. 用户输入目标值
cout << "请输入要查找的员工编号:";
cin >> target;
// 2. 遍历数组查找目标值
for (int i = 0; i < length; i++) {
if (ids[i] == target) {
index = i; // 找到目标值,记录下标
break; // 找到后立即退出循环,提高效率
}
}
// 3. 输出查找结果
if (index != -1) {
cout << "找到目标值 " << target << ",对应的下标是:" << index << endl;
} else {
cout << "未找到目标值 " << target << endl;
}
return 0;
}
运行场景 1(找到目标值):
请输入要查找的员工编号:103
找到目标值 103,对应的下标是:2
运行场景 2(未找到目标值):
请输入要查找的员工编号:106
未找到目标值 106
5. 综合案例:数组多操作结合(动态赋值 + 排序 + 找最值)
需求:让用户输入 6 个学生的英语成绩,动态存入数组后,先按从高到低排序,再找出最高分和最低分,最后输出排序后的成绩、最高分和最低分。
#include
using namespace std;
int main() {
const int STUDENT_NUM = 6;
int scores[STUDENT_NUM];
// 1. 动态赋值:用户输入6个成绩
cout << "请输入6个学生的英语成绩:" << endl;
for (int i = 0; i < STUDENT_NUM; i++) {
cout << "第" << (i + 1) << "个学生成绩:";
cin >> scores[i];
}
// 2. 冒泡排序(从高到低)
for (int i = 0; i < STUDENT_NUM - 1; i++) {
for (int j = 0; j < STUDENT_NUM - 1 - i; j++) {
if (scores[j] < scores[j + 1]) { // 前小后大则交换(从高到低)
int temp = scores[j];
scores[j] = scores[j + 1];
scores[j + 1] = temp;
}
}
}
// 3. 找最高分和最低分(排序后,第一个元素是最高分,最后一个是最低分)
int maxScore = scores[0];
int minScore = scores[STUDENT_NUM - 1];
// 4. 输出结果
cout << "\n排序后的成绩(从高到低):";
for (int i = 0; i < STUDENT_NUM; i++) {
cout << scores[i] << " ";
}
cout << "\n最高分:" << maxScore << endl;
cout << "最低分:" << minScore << endl;
return 0;
}
运行结果:
请输入6个学生的英语成绩:
第1个学生成绩:82
第2个学生成绩:95
第3个学生成绩:78
第4个学生成绩:100
第5个学生成绩:88
第6个学生成绩:92
排序后的成绩(从高到低):100 95 92 88 82 78
最高分:100
最低分:78
6. ⚠️ 拓展操作常见错误
错误 1:找最值时,初始值设为 0(而非数组第一个元素)
如果数组中所有元素都是负数(比如{-5, -3, -8}),初始值设为 0 会导致最大值判断错误:
// 错误:初始值设为0,数组全为负数时,0会被当作最大值
int maxVal = 0;
for (int i = 0; i < length; i++) {
if (arr[i] > maxVal) maxVal = arr[i]; // 最终maxVal=0,而非-3
}
✅ 正确:初始值必须设为数组第一个元素(arr[0]),确保覆盖所有元素情况。
错误 2:冒泡排序时,内层循环条件写错(未减去轮次 i)
// 错误:内层循环条件未减i,导致已排序的元素重复对比
for (int j = 0; j < length - 1; j++) {
// 最后i轮的元素已排序,无需再对比,会浪费效率甚至出错
}
✅ 正确:内层循环条件写j < length - 1 - i,每轮减少对比次数。
错误 3:查找元素时,未处理 “多个相同元素” 的情况
如果数组中有多个相同的目标值(比如{10, 20, 10, 30}),默认只返回第一个匹配元素的下标,若需要返回所有下标,需删除break:
// 查找所有相同元素的下标
for (int i = 0; i < length; i++) {
if (arr[i] == target) {
cout << "找到目标值,下标:" << i << endl; // 不break,继续查找
}
}
7. 下节预告:do-while 循环详解(先执行后判断的循环新方式)
本节课我们掌握了数组的找最值、排序和查找操作,能灵活处理数组数据了。接下来,我们要学习一种新的循环结构 ——do-while 循环。
它和之前学的 while 循环最大的区别是:while 循环 “先判断后执行”,可能一次都不执行;而 do-while 循环 “先执行后判断”,至少执行一次。这种特性特别适合 “需要先做一次操作,再判断是否继续” 的场景:
- 游戏场景:“先让玩家玩一局游戏,再询问是否继续玩”;
- 输入验证:“先让用户输入密码,再判断密码是否正确,不正确则重新输入”。
下节课我们会学习:
- do-while 循环的语法结构与执行原理;
- do-while 与 while 循环的区别(什么时候该用 do-while);
- do-while 循环的实战案例(输入验证、简单游戏循环)。
学会 do-while 循环后,你能应对更多 “必须先执行一次” 的场景,让循环


浙公网安备 33010602011771号