5 数组
5.1 概述
所谓数组,就是一个集合,里面 有序地 存放了 相同类型 的数据元素。
特点1: 数组中的每个数据元素都是相同的数据类型
特点2: 数组中的元素,按顺序排列,在内存中占据一块连续的内存区域,数组名实际上就是这块空间的名称。
因为数组名实际上就是内存空间的名称。所以,之间输出数组名,将得到此数组内存空间的起始地址。使用
sizeof 数组名
将得到此数组内存空间的大小。
5.2 一维数组
5.2.1 一维数组的基础定义方式
定义方式:
数据类型 数组名[ 数组长度 ];
说明:
- 数组名的命名规范与变量名命名规范一致;数组不要和变量重名。
- 声明数组的长度时,不能使用变量。
- 在数组定义时,给所有数组元素赋初值,可以省略数组长度。
在C++的标准中,不允许使用变量作为数组长度。但在实际编写C++代码时,编译器可能允许使用。
示例
#define N 10
int main() {
const int SIZE = 20;
int size;
cin>>size;
int a[50];
int b[N];
int c[SIZE];
int d[size]; //不一定正确
return 0;
}
5.2.2 使用下标访问一维数组元素
用户需要使用下标运算符([ ])来访问数组的的元素。
语法:
数组名[ 下标 ];
注意: 下标从0开始。
示例
int main() {
//数据类型 数组名[元素个数];
int score[10];
//利用下标赋值
score[0] = 100;
score[1] = 99;
score[2] = 85;
//利用下标输出
cout << score[0] << endl;
cout << score[1] << endl;
cout << score[2] << endl;
return 0;
}
5.2.3 一维数组的遍历
依次访问每一个数组元素的过程,叫做数组的遍历。
方法:
- 使用for循环访问使用下标
- 使用基于范围的 for 语句
示例
#include<iostream>
#include <algorithm>
using namespace std;
int main() {
int score[3];
//利用下标赋值
score[0] = 100;
score[1] = 99;
score[2] = 85;
// 1. 使用for循环访问使用下标
for (int i = 0; i < 3; i++)
{
cout << score[i] << endl;
}
// 2. 使用基于范围的 for 语句
for (int i : score)
{
cout << i << endl;
}
return 0;
}
5.2.4 一维数组的初始化
在定义数组时,可以对数组元素指定初值,这被称为数组的初始化。
初始化方式:
- 不初始化
如果数组为全局变量或静态局部变量,数组所有元素初值为0;如果数组为局部变量,初值为随机值。
#include<iostream>
#include <algorithm>
using namespace std;
int a[3];
int main() {
int b[3];
// 数组为全局变量,数组所有元素初值为0
for (int i : a)
{
cout << i << endl;
}
// 数组为局部变量,数组所有元素初值为随机值
for (int i : b)
{
cout << i << endl;
}
return 0;
}
- 对所有元素赋初值
语法: 数据类型 数组名[ 数组长度 ] = {值1, 值2,...最后一个元素的值}
注意: 这种情况下,可以省略数组长度。因为编译器可以推测数组长度。
示例:
// 以下两种方式等价
int a[10] = {100, 90, 80, 70, 60, 50, 40, 30, 20, 10};
int b[] = {100, 90, 80, 70, 60, 50, 40, 30, 20, 10};
- 对部分元素赋初值
语法: 数据类型 数组名[ 数组长度 ] = {值1, 值2,...}
注意: 这种情况下,值被依次分配,未能分配到初值的元素,将被赋初值0。
示例:
int main() {
int a[10] = {100};
for (int i: a) {
cout << i << endl;
}
return 0;
}
5.2.5 一维数组案例
案例:从键盘输入数组中的每个元素的值,然后获取数组中的最大值。
参考代码:
int main() {
int a[5];
// 输入每个元素的值
// 这种基于范围的for语句,不可以实现输入效果
// for (int i: a) {
// cin >> i;
// }
// 这种基于范围的for语句,可以实现输入效果
// for (int & i: a) {
// cin >> i;
// }
// 现在会这种方式就可以
for (int i = 0; i < 5; ++i) {
cin >> a[i];
}
int max = 0;
for (int i: a) {
max = max > i ? max : i;
}
cout << max << endl;
return 0;
}
5.2.6 冒泡排序
作用: 最常用的排序算法,对数组内元素进行排序
- 比较相邻的元素。如果第一个比第二个大,就交换他们两个。
- 对每一对相邻元素做同样的工作,执行完毕后,找到第一个最大值。
- 重复以上的步骤,每次比较次数-1,直到不需要比较
动画分析: 冒泡排序动画
示例:
int main() {
const int length = 10;
int arr[length] = {15,45,10,16,11,7,50,42,44, 11};
bool swapped = false;
for (int i = 0; i < length - 1; i++)
{
swapped = false;
for (int j = 0; j < length - 1 - i; j++)
{
if (arr[j] > arr[j + 1])
{
// int temp = arr[j];
// arr[j] = arr[j + 1];
// arr[j + 1] = temp;
swap(arr[j], arr[j+1]);
swapped = true;
}
}
cout << "第" << i + 1 << "次冒泡后:" << endl;
for (int num: arr) {
cout << num << " ";
}
cout << endl;
if (!swapped){
cout << "数组元素排序完成,循环提前结束" << endl;
break;
}
}
return 0;
}
5.3 二维数组
二维数组就是在一维数组上,多加一个维度。
说明:
- C++对数组维度没有限制,可以从二维数组推广到三维、四维。
- 二维数组在内存中,按行存放。即对于
int a[2][3]
,内存中的顺序为:a[0][0]
,a[0][1]
,a[0][2]
,a[1][0]
,a[1][1]
,a[1][2]
。
5.3.1 二维数组的定义与初始化
二维数组定义与初始化的四种方式:
- 仅定义
数据类型 数组名[ 行数 ][ 列数 ];
- 分行给二维数组初始化
数据类型 数组名[ 行数 ][ 列数 ] = { {数据1,数据2 } ,{数据3,数据4 } };
- 此时第一维(行数)可以省略。编辑器将根据数据中的行数推测。
- 赋值时,数据可以不写全,未赋值的元素将被赋0。
int a[3][4] = {{1, 2}, {3}};
- 逐个为数组元素赋值
数据类型 数组名[ 行数 ][ 列数 ] = { 数据1,数据2,数据3,数据4};
- 此时第一维(行数)可以省略。编辑器将根据数据数量除以列数的结果推测行数。
- 赋值时,数据可以不写全,未赋值的元素将被赋0。
int a[3][4] = {1, 2, 3};
5.3.2 二维数组应用案例
考试成绩统计:
案例描述:有三名同学(张三,李四,王五),在一次考试中的成绩分别如下表,请分别输出三名同学的总成绩
语文 | 数学 | 英语 | |
---|---|---|---|
张三 | 100 | 100 | 100 |
李四 | 90 | 50 | 100 |
王五 | 60 | 70 | 80 |
参考答案:
int main() {
int scores[3][3] =
{
{100,100,100},
{90,50,100},
{60,70,80},
};
string names[3] = { "张三","李四","王五" };
for (int i = 0; i < 3; i++)
{
int sum = 0;
for (int j = 0; j < 3; j++)
{
sum += scores[i][j];
}
cout << names[i] << "同学总成绩为: " << sum << endl;
}
return 0;
}