@鞠大龙 魅客科创中心
// 一个存储5个整数的数组示例 int numbers[5] = {1, 2, 3, 4, 5}; // 数组在内存中的示意图 // [1][2][3][4][5] // ↑ // 数组的第一个元素(下标为0)
优点:
使用场景:
注意事项:
int scores[3]; // 创建数组 // 正确的访问 scores[0] = 85; scores[1] = 92; scores[2] = 78; // 错误的访问(越界) scores[3] = 90; // 危险!
不使用数组的情况:
int score1 = 85; int score2 = 92; int score3 = 78; int score4 = 95; int score5 = 88; double average = (score1 + score2 + score3 + score4 + score5) / 5.0;// 计算平均分
使用数组的情况:
int scores[5] = {85, 92, 78, 95, 88};// 使用数组存储5个学生的成绩 int sum = 0; for(int i = 0; i < 5; i++) { sum += scores[i]; } double average = sum / 5.0;
基本语法:
数据类型 数组名[数组大小];
示例:
int numbers[10]; // 声明一个包含10个整数的数组 char letters[5]; // 声明一个包含5个字符的数组 double values[100]; // 声明一个包含100个浮点数的数组 // 数组大小必须是常量或常量表达式 const int SIZE = 20; int data[SIZE]; // 错误的声明方式 int n = 10; int wrong[n]; // 错误:数组大小必须是常量
完整初始化:
// 方法1:使用花括号 int numbers[5] = {1, 2, 3, 4, 5}; // 方法2:声明时不指定大小 int numbers[] = {1, 2, 3, 4, 5}; // 编译器会自动计算大小 // 方法3:全部初始化为0 int numbers[5] = {0};
部分初始化:
// 只初始化部分元素 int numbers[5] = {1, 2}; // 其余元素自动设为0 // numbers = {1, 2, 0, 0, 0} // 错误的初始化方式 int numbers[3] = {1, 2, 3, 4}; // 错误:初始值太多 int numbers[5]; numbers = {1, 2, 3, 4, 5}; // 错误:不能整体赋值
// 1. 未初始化的数组 int numbers[5]; // 数组元素的值是随机的 // 2. 初始化值过多 int numbers[3] = {1, 2, 3, 4, 5}; // 错误 // 3. 使用变量作为数组大小 int size = 5; int numbers[size]; // 错误:必须使用常量 // 4. 试图在声明后整体赋值 int numbers[5]; numbers = {1, 2, 3, 4, 5}; // 错误 // 正确的做法 const int SIZE = 5; // 使用常量定义大小 int numbers[SIZE] = {0}; // 全部初始化为0 // 然后逐个赋值 for(int i = 0; i < SIZE; i++) { numbers[i] = i + 1; }
0
数组大小-1
[]
int numbers[5] = {10, 20, 30, 40, 50}; // 访问数组元素 cout << numbers[0] << endl; // 输出:10 cout << numbers[4] << endl; // 输出:50 // 使用变量作为下标 int index = 2; cout << numbers[index] << endl; // 输出:30 // 注意:访问越界会导致未定义行为 cout << numbers[5] << endl; // 错误:下标越界
直接赋值:
int numbers[5] = {1, 2, 3, 4, 5}; // 修改单个元素 numbers[0] = 10; numbers[4] = 50; // 使用变量 int index = 2; int value = 30; numbers[index] = value; // 使用表达式 numbers[1] = numbers[0] * 2;
常见错误:
int numbers[5] = {1, 2, 3, 4, 5}; // 越界访问 numbers[5] = 60; // 错误 // 使用负数下标 numbers[-1] = 0; // 错误 // 使用过大的下标 int i = 10; numbers[i] = 100; // 错误 // 没有边界检查 // C++不会自动检查数组越界 // 需要程序员自己确保下标合法
为了安全访问数组,我们应该:
const int SIZE = 5; int numbers[SIZE] = {1, 2, 3, 4, 5}; // 安全的数组访问 if(index >= 0 && index < SIZE) { value = numbers[index]; }
遍历就是按照某种顺序访问数组中的元素
const int SIZE = 5; int numbers[SIZE] = {1, 2, 3, 4, 5}; // 正向遍历 for(int i = 0; i < SIZE; i++) { cout << numbers[i] << " "; } // 输出:1 2 3 4 5 // 反向遍历 for(int i = SIZE - 1; i >= 0; i--) { cout << numbers[i] << " "; } // 输出:5 4 3 2 1 // 按步长遍历(每次跳过一个元素) for(int i = 0; i < SIZE; i += 2) { cout << numbers[i] << " "; } // 输出:1 3 5
修改元素:
for(int i = 0; i < SIZE; i++) { numbers[i] *= 2;// 将所有元素乘以2 } for(int i = 0; i < SIZE; i++) { numbers[i] += i;// 将所有元素加上下标值 }
统计信息:
int sum = 0; for(int i = 0; i < SIZE; i++) { sum += numbers[i];// 计算元素和 } double average = (double)sum / SIZE;// 计算平均值
条件处理:
// 统计偶数的个数 int count = 0; for(int i = 0; i < SIZE; i++) { if(numbers[i] % 2 == 0) { count++; } } // 查找特定值 int target = 3; bool found = false; for(int i = 0; i < SIZE; i++) { if(numbers[i] == target) { found = true; break; } }
const int SIZE = 5; int numbers[SIZE] = {1, 2, 3, 4, 5}; // 正确的循环边界 for(int i = 0; i < SIZE; i++) // 使用 < 而不是 <= // 错误的循环边界 for(int i = 1; i <= SIZE; i++) // 从1开始会漏掉第一个元素 for(int i = 0; i <= SIZE; i++) // 使用<=会导致越界
for(int i = 0; i < SIZE; i++) { // 危险:在循环中修改i可能导致越界或无限循环 if(numbers[i] < 0) { i--; // 不要这样做! } }
const int SIZE = 5; // 使用常量便于维护 int numbers[SIZE]; // 数组大小使用常量 // 避免使用魔法数字 for(int i = 0; i < 5; i++) // 不好 for(int i = 0; i < SIZE; i++) // 好
const int SIZE = 5; int numbers[SIZE] = {1, 3, 5, 2, 4}; // 1. 查找特定值 int target = 3; int findIndex = -1; // 存储找到的位置,-1表示未找到 for(int i = 0; i < SIZE; i++) { if(numbers[i] == target) { findIndex = i; break; } } // 2. 查找最大值 int maxValue = numbers[0]; // 假设第一个元素是最大的 int maxIndex = 0; for(int i = 1; i < SIZE; i++) { if(numbers[i] > maxValue) { maxValue = numbers[i]; maxIndex = i; } } // 3. 查找最小值 int minValue = numbers[0]; int minIndex = 0; for(int i = 1; i < SIZE; i++) { if(numbers[i] < minValue) { minValue = numbers[i]; minIndex = i; } }
计算总和与平均值:
int numbers[5] = {1, 2, 3, 4, 5}; // 计算总和 int sum = 0; for(int i = 0; i < 5; i++) { sum += numbers[i]; } // 计算平均值 double average = (double)sum / 5;
统计符合条件的元素:
// 统计偶数个数 int evenCount = 0; for(int i = 0; i < 5; i++) { if(numbers[i] % 2 == 0) { evenCount++; } }
计算最大和最小值的差:
// 找出最大和最小值 int max = numbers[0]; int min = numbers[0]; for(int i = 1; i < 5; i++) { if(numbers[i] > max) { max = numbers[i]; } if(numbers[i] < min) { min = numbers[i]; } } // 计算差值 int difference = max - min;
const int SIZE = 5; int numbers[SIZE] = {1, 2, 3, 4, 5}; // 1. 所有元素加上一个值 int addValue = 10; for(int i = 0; i < SIZE; i++) { numbers[i] += addValue; } // 2. 所有元素乘以一个值 int multiplyValue = 2; for(int i = 0; i < SIZE; i++) { numbers[i] *= multiplyValue; } // 3. 数组元素反转 for(int i = 0; i < SIZE/2; i++) { // 交换首尾对应的元素 int temp = numbers[i]; numbers[i] = numbers[SIZE-1-i]; numbers[SIZE-1-i] = temp; } // 4. 将所有负数变成0 for(int i = 0; i < SIZE; i++) { if(numbers[i] < 0) { numbers[i] = 0; } }
const int SIZE = 5; int numbers[SIZE] = {4, 2, 5, 1, 3}; // 冒泡排序(从小到大) for(int i = 0; i < SIZE-1; i++) { for(int j = 0; j < SIZE-1-i; j++) { if(numbers[j] > numbers[j+1]) { // 交换相邻的两个元素 int temp = numbers[j]; numbers[j] = numbers[j+1]; numbers[j+1] = temp; } } } // 选择排序(从小到大) for(int i = 0; i < SIZE-1; i++) { // 找出第i个位置后面最小的元素 int minIndex = i; for(int j = i+1; j < SIZE; j++) { if(numbers[j] < numbers[minIndex]) { minIndex = j; } } // 将找到的最小元素放到第i个位置 if(minIndex != i) { int temp = numbers[i]; numbers[i] = numbers[minIndex]; numbers[minIndex] = temp; } }
// 方法1:使用数组作为参数 void printArray(int arr[], int size) { for(int i = 0; i < size; i++) { cout << arr[i] << " "; } cout << endl; } // 方法2:使用指针作为参数(效果相同) void printArray(int* arr, int size) { for(int i = 0; i < size; i++) { cout << arr[i] << " "; } cout << endl; } int main() { const int SIZE = 5; int numbers[SIZE] = {1, 2, 3, 4, 5}; // 调用函数 printArray(numbers, SIZE); return 0; }
修改数组元素:
// 将数组所有元素加倍 void doubleElements(int arr[], int size) { for(int i = 0; i < size; i++) { arr[i] *= 2; } } int main() { int numbers[5] = {1, 2, 3, 4, 5}; doubleElements(numbers, 5); // numbers现在是{2,4,6,8,10} return 0; }
// 错误示例:返回局部数组 int[] wrongFunction() { int arr[5] = {1,2,3,4,5}; return arr; // 错误! }
// 1. 计算数组元素和 int getSum(const int arr[], int size) { int sum = 0; for(int i = 0; i < size; i++) { sum += arr[i]; } return sum; } // 2. 查找最大值 int findMax(const int arr[], int size) { if(size == 0) return 0; // 处理空数组 int max = arr[0]; for(int i = 1; i < size; i++) { if(arr[i] > max) { max = arr[i]; } } return max; } // 3. 复制数组 void copyArray(const int source[], int target[], int size) { for(int i = 0; i < size; i++) { target[i] = source[i]; } } // 使用示例 int main() { const int SIZE = 5; int numbers[SIZE] = {1, 2, 3, 4, 5}; int copy[SIZE]; cout << "Sum: " << getSum(numbers, SIZE) << endl; cout << "Max: " << findMax(numbers, SIZE) << endl; copyArray(numbers, copy, SIZE); return 0; }
题目说明:
int main() { const int SIZE = 10; int scores[SIZE]; // 输入成绩 cout << "请输入" << SIZE << "个学生的成绩:" << endl; for(int i = 0; i < SIZE; i++) { cin >> scores[i]; } // 计算统计数据 int sum = 0, max = scores[0], min = scores[0]; int passCount = 0; // 及格人数 for(int i = 0; i < SIZE; i++) { sum += scores[i]; if(scores[i] > max) max = scores[i]; if(scores[i] < min) min = scores[i]; if(scores[i] >= 60) passCount++; } // 输出结果 cout << "平均分:" << (double)sum / SIZE << endl; cout << "最高分:" << max << endl; cout << "最低分:" << min << endl; cout << "及格人数:" << passCount << endl; cout << "及格率:" << (double)passCount / SIZE * 100 << "%" << endl; return 0; }
bool checkSudokuRow(int row[], int size) { // 创建一个数组记录数字是否出现 bool used[10] = {false}; // 0号位置不使用 // 检查每个数字 for(int i = 0; i < size; i++) { // 检查数字是否在1-9范围内 if(row[i] < 1 || row[i] > 9) { return false; } // 检查数字是否重复 if(used[row[i]]) { return false; // 数字已经出现过 } used[row[i]] = true; // 标记数字已使用 } // 检查是否使用了所有数字1-9 for(int i = 1; i <= 9; i++) { if(!used[i]) { return false; // 缺少数字 } } return true; // 行合法 } int main() { int sudokuRow[9] = {5, 3, 4, 6, 7, 8, 9, 1, 2}; if(checkSudokuRow(sudokuRow, 9)) { cout << "数独行合法" << endl; } else { cout << "数独行不合法" << endl; } return 0; }
class Scoreboard { private: const static int MAX_SCORES = 5; // 保存最近5局分数 int scores[MAX_SCORES]; // 分数数组 int count; // 当前记录的分数数量 public: // 构造函数 Scoreboard() { count = 0; for(int i = 0; i < MAX_SCORES; i++) { scores[i] = 0; } } // 添加新分数 void addScore(int score) { // 移动所有分数 for(int i = MAX_SCORES - 1; i > 0; i--) { scores[i] = scores[i-1]; } // 在开头添加新分数 scores[0] = score; // 更新计数 if(count < MAX_SCORES) count++; } // 显示所有分数 void displayScores() { cout << "最近" << count << "局游戏分数:" << endl; for(int i = 0; i < count; i++) { cout << "第" << i+1 << "局:" << scores[i] << endl; } // 计算并显示平均分 if(count > 0) { int sum = 0; for(int i = 0; i < count; i++) { sum += scores[i]; } cout << "平均分:" << (double)sum / count << endl; } } }; int main() { Scoreboard board; // 添加一些测试分数 board.addScore(100); board.addScore(85); board.addScore(95); board.displayScores(); cout << "\n添加更多分数:\n" << endl; board.addScore(75); board.addScore(90); board.addScore(88); // 这将删除最早的分数(100) board.displayScores(); return 0; }
初级题目:
HDU 2000 - ASCII码排序 (★☆☆☆☆)
HDU 2001 - 计算两点间的距离 (★☆☆☆☆)
NOIP 2008 普及组 - 排座椅 (★★☆☆☆)
中级题目:
CSP-J 2019 - 数字游戏 (★★☆☆☆)
USACO 2019 Bronze - Bucket Brigade (★★☆☆☆)
POJ 3094 - Quicksum (★★☆☆☆)
1. CSP-J 2022 - 解密 (★★★☆☆)
2. NOIP 2012 普及组 - 质因数分解 (★★★☆☆)
3. CSES - Missing Number (★★☆☆☆)
4. USACO 2017 Bronze - Why Did the Cow Cross the Road (★★★☆☆)
安全性:
可维护性:
效率:
进阶学习:
感谢学习! 如有疑问,请联系: judal@xmaker.org 魅客科创中心
内容针对初学者设计,使用简单易懂的语言和示例。 假设学生已经了解基本数据类型、循环和判断语句。