C++数组的查找与统计
较难18在数组中查找和统计:像侦探一样寻找线索
想象一下,你有一堆同学的成绩单,你想知道有没有人考了100分?或者想知道全班有多少人及格了?在编程中,这些操作分别叫做查找(找某个值是否存在)和统计(数数某个条件满足了几次)。数组就像一列整齐的储物柜,里面装着数据,我们只需要按顺序检查每个柜子就行了。
1. 顺序查找:一个一个问,直到找到答案
顺序查找是最简单的方法:从数组的第一个元素开始,挨个和要找的目标比较。如果相等,就说明找到了,可以记录位置并停下来。如果全部比较完都没找到,那就是不存在。
生活例子:在排队找朋友
你和朋友约好在电影院见面,但队伍很长,你不知道他在哪。你只能从队伍第一个人开始,一个个看脸:“是你吗?”如果不是,继续看下一个。直到找到朋友,或者走到队伍尽头。
代码实现:找有没有77分
下面的程序检查一个成绩数组里是否包含77分。如果找到,就输出它的位置(下标),并用一个布尔变量found记录是否找到。
#include <iostream>
using namespace std;
int main() {
int scores[7] = {88, 72, 77, 95, 77, 60, 45}; // 7个成绩
int target = 77; // 要查找的目标分数
bool found = false; // 标记:是否找到,初始为false
// 从第一个元素开始,逐个比较
for(int i = 0; i < 7; i++) {
if(scores[i] == target) {
found = true; // 找到了
cout << "找到了77分,位置是下标 " << i << endl;
break; // 如果只想找第一次出现,就及时退出循环
}
}
if(!found) {
cout << "没有找到 " << target << " 分" << endl;
}
return 0;
}
注意:break会让循环提前结束。如果数组里有多个77分,上面的程序只会报告第一个出现的位置。如果你想找出所有位置,可以删除break,并在循环结束后看看found是不是true。
进阶:记录所有位置
如果想输出所有77分的位置,可以去掉break,并在循环外判断是否找到:
#include <iostream>
using namespace std;
int main() {
int scores[7] = {88, 72, 77, 95, 77, 60, 45};
int target = 77;
bool found = false; // 标记是否至少找到一个
cout << target << "分出现的位置: ";
for(int i = 0; i < 7; i++) {
if(scores[i] == target) {
found = true;
cout << i << " "; // 逐个输出下标,不换行
}
}
if(!found) {
cout << "没有";
}
cout << endl;
return 0;
}
2. 统计计数:数一数满足条件的有几个
统计比查找多一个步骤:不是找到就停,而是每遇到一个满足条件的,就把计数器加1。循环结束后,计数器的值就是结果。
生活例子:数苹果里红色的有几个
你有8个苹果,颜色分别是红、绿、红、黄、红、红、绿、绿。你想知道红色苹果有几个。于是你一个一个看,“这个是红色吗?是,计数器加1……不是,跳过。”最后计数器显示有4个红色苹果。
代码实现:统计及格人数和具体分数出现次数
下面统计成绩数组中大于等于60分的人数(及格人数),以及60分本身出现了几次。
#include <iostream>
using namespace std;
int main() {
int scores[8] = {72, 58, 90, 45, 88, 60, 95, 50};
int passCount = 0; // 及格人数计数器,初始为0
for(int i = 0; i < 8; i++) {
if(scores[i] >= 60) {
passCount++; // 每遇到一个及格的就加1
}
}
cout << "及格人数: " << passCount << endl;
// 也可以统计某个特定值出现了几次,比如60分
int count60 = 0;
for(int i = 0; i < 8; i++) {
if(scores[i] == 60) {
count60++;
}
}
cout << "60分出现的次数: " << count60 << endl;
return 0;
}
注意:统计时不需要break,因为我们要检查所有元素。计数器每次加1,最后的值就是总数。
3. 条件统计:按范围或特征统计
除了统计等于某个值,还可以统计满足某个范围(比如90分以上、不及格人数)或某个特征(比如是偶数)的元素个数。方法完全一样,只是if里的条件不同。
例子:统计90分以上的学霸人数
int highScoreCount = 0; // 90分以上的人数
for(int i = 0; i < 8; i++) {
if(scores[i] > 90) {
highScoreCount++;
}
}
cout << "90分以上的人数: " << highScoreCount << endl;
例子:统计不及格人数(小于60)
int failCount = 0; // 不及格人数
for(int i = 0; i < 8; i++) {
if(scores[i] < 60) {
failCount++;
}
}
cout << "不及格人数: " << failCount << endl;
4. 新手容易犯的错误
- 忘记初始化计数器:如果没给
passCount设初始值(比如直接int passCount;),它的值可能是随机的,加出来的结果也乱七八糟。一定要初始化为0。 - 在查找时忘记用
break:如果只是想找“有没有”,找到后不退出循环,会继续比较后面的元素,虽然逻辑上没错,但浪费了时间。如果还记录了位置,最后的位置会是最后一个出现的位置,而不是第一个。 - 用
=代替==:if(scores[i] = target)是赋值,不是比较。赋值表达式的值是赋的值,在C++中非零为真,所以永远会进入if块。这是最常见的笔误。 - 数组下标越界:循环条件写成
i <= 数组长度,会访问数组最后一个元素后面的位置,程序可能崩溃。记住数组下标从0开始,最大下标是数组长度-1。
5. 完整示例:查找最高分和统计人数
下面把查找和统计结合起来:找出最高分,并统计有多少人达到了这个最高分。
#include <iostream>
using namespace std;
int main() {
int scores[10] = {72, 88, 95, 91, 73, 95, 68, 82, 95, 60}; // 10人的成绩
int maxScore = scores[0]; // 假设第一个是最高分
int maxCount = 0; // 最高分出现次数
// 第一步:找出最高分
for(int i = 1; i < 10; i++) { // 从第二个开始比较
if(scores[i] > maxScore) {
maxScore = scores[i]; // 更新最高分
}
}
// 第二步:统计最高分出现了几次
for(int i = 0; i < 10; i++) {
if(scores[i] == maxScore) {
maxCount++;
}
}
cout << "最高分是: " << maxScore << endl;
cout << "获得最高分的人数: " << maxCount << endl;
return 0;
}
6. 相关指引
学会了数组的查找和统计,你可以:
- 结合“数组的排序”(比如冒泡排序)来做更高级的数据分析,比如找出中位数。
- 用二维数组(类似表格)查找某个同学的姓名对应的分数。
- 用函数封装查找和统计的代码,让主程序更简洁。
- 进一步学习“二分查找”,它比顺序查找更快,但要求数组事先排好序。
查找和统计就像在图书馆里找书(查找)或者数一数红色封面的书有几本(统计)。掌握了这两个基本操作,你就能用数组解决很多生活里的数据问题啦!
例题精讲
假设有一个整型数组 `int arr[5] = {3, 1, 4, 1, 5};`,要统计数字 1 出现的次数,以下哪个代码片段是正确的?
在长度为 n 的无序数组中查找某个值,如果该值不存在,需要比较全部 n 个元素才能确定。
以下代码实现了在数组 `a` 中查找最大值并返回其下标的功能。请补全缺失的代码。
int findMaxIndex(int a[], int n) {
int maxIdx = 0;
for (int i = 1; i < n; i++) {
if (___)
maxIdx = i;
}
return maxIdx;
}统计整数数组 `arr` 中所有大于 0 的元素的个数,并将结果返回。补全代码。
int countPositive(int arr[], int size) {
int cnt = 0;
for (int i = 0; i < size; i++) {
if (___)
cnt++;
}
return cnt;
}对于长度为 10 的整型数组,下列哪种说法是关于顺序查找(线性查找)的正确描述?