一维数组¶
数组的定义¶
一组相同类型的数据,可以放进数组里,按编号访问。
开了一个名字叫小 a 的数组,可以存 110 个 int。这些元素在内存中连续存放。
数组开多大?
看题目最多有多少个数据,再看下标从哪里开始。
100 个数据,从 0 开始存,用到 a[0] 到 a[99];从 1 开始存,用到 a[1] 到 a[100]。
做题时,通常留一点余量,开 a[110]。但多开几个位置,不代表可以随意访问。
数组的访问,下标¶
数组下标从 0 开始。
int a[5] = {10, 20, 30, 40, 50};
cout << a[0]; // 第一个元素,10
cout << a[4]; // 最后一个元素,50
a[2] = 99; // 把第三个元素改成99
a[i] 表示下标为 i 的元素,不能把“第几个”和“下标”混了。
从 1 开始存,也是可以的。
这是我们选择不用 a[0],不是数组的下标规则变了。
数组的初始化¶
数组开全局
做题时,数组一般开在 main 外面。没有另外初始化的全局数组,元素默认都是 0。
普通局部数组不一样:写在函数里面,没有初始化,就不能直接读取它的值。
使用大括号初始化
数组的输入输出¶
这里 0 <= n <= 100,从下标 0 开始存。
#include <iostream>
using namespace std;
int a[110];
int main() {
int n;
cin >> n;
for (int i = 0; i < n; i++) cin >> a[i];
for (int i = 0; i < n; i++) cout << a[i] << ' ';
return 0;
}
数组的遍历¶
遍历,就是把需要处理的元素,一个一个访问一遍。
从左向右
从右向左
用常量开数组¶
多个数组需要相同的容量,用常量统一写,避免多写、少写一个 0。
const 表示这里的 N 是常量,定义后不能重新赋值。
常用数组名称¶
| 数组名称 | 单词全拼 | 使用场景 |
|---|---|---|
a[]、arr[] |
array | 通用数组名 |
cnt[] |
count | 计数数组 |
dis[]、d[] |
distance | 距离、步数 |
vis[]、st[] |
visited、state | 是否访问过、状态 |
s[] |
string | 字符数组 |
常见错误¶
数组越界
int a[10]; 的有效下标是 0 到 9,a[-1]、a[10] 都越界。
越界不一定立刻报错,也可能悄悄产生错误结果,不能靠“运行没崩溃”判断对错。
数组长度,不直接用读入的 n
本阶段按题目上限,用常量开数组。不要把“编译器碰巧支持”当成通用写法。
容量与实际个数,不是一回事。
开了 a[110],只输入了 n 个数,处理数据时就按 n 遍历,不是把 110 个位置都算进去。
数组不能直接整体赋值。
不能用 a = b; 复制两个普通数组,要循环逐个复制对应元素。
memset(先不看)¶
需要头文件 <cstring>。
sizeof a 是整个数组占用的字节数,不是元素个数。这里的 a 要是数组本身。
常见环境中,对 int 数组还会看到:
0x3f3f3f3f 常用作一个较大的初始值,不是 int 的最大值。
memset 按字节填充。 不能写 memset(a, 1, sizeof a),就认为每个整数都变成 1。
想把每个元素设成 1,可以用循环逐个赋值。原理等学过二进制后,再看memset。