一、什么是数组
1、与数学的联系——数列
关于数组,你可以就把他当作数学上的“数列”,用来存一系列的数。
数学上的一个数列$a_i$:
当$i=1$时,代表的是这个数列的第一个数$a_1$,当$i=3$时,代表的是这个数列的第三个数$a_3$……
同时,这个数列可以叫数列$a_i$,也可以叫$b_i、{nico}_i$……
可以用$i$来表示第几项($a_i$),也可以用$j$来表示第几项($a_j$)……
2、与数学的不同
- 数学上的数列是从第一项开始的,也就是$a_1$代表的就是$a$这个数列的第一项。
然而编程里的数组,却是从第零项开始的,也就是a[1]
代表的是a
这个数组里第二项,a[0]
才是第一项。 - 数学上的数列,我们不需要提前告诉这个数列中会有多少项。
然而编程里的数组,我们需要提前告诉他这个数组里会有多少项,也就是int a[100]
的100
的意思,代表可能会存100项。
3、编程中的数组
那么类比到我们编程里:
- 这个$a_i$的$a$,就是程序里的这个数组的名字,专业名称叫“变量名”。
- 这个$a_i$的$i$,就是程序里的这个数组的第几项,专业名称叫“下标”。
比如arr[5]
代表的就是arr
这个数组里的第6项。
二、数组的声明
申明部分,也就是定义。如:
int arr[100];
int
——代表的是这个数组的类型:即这个数组存的是一系列int类型的数。
arr
——代表的是这个数组的变量名,之后用这个数组就是arr[2]
、arr[i]
之类的形式。
[100]
——代表的是这个数组的大小,也就是可能会存多少项。
对于数组大小的声明,必须为常量或者常量表达式。
正确的例子:
int a[10]; //字面常量(常数)
int b[5 * 5]; //字面常量的表达式
const int len = 10;
int c[len]; //符号常量
int d[len * 2]; //符号常量的表达式
错误的例子:
int len = 10;
int a[len]; //len为变量,错误
int a[len + 5]; //len+5为变量相关的表达式,错误
三、数组的运用
1、对一个数组某个具体元素的运用
-
最简单的运用,我们直接把一个常数
100
存到arr
数组里的第三项里:a[2] = 100;
-
要把一个变量
val
存到arr
数组里的第一项里:a[0] = val;
-
要输出数组
arr
中的第二项:cout << a[1];
2、对一个数组多个元素的运用
很多时候我们不止运用其中的某一个具体的数。
比如我们要向这个数组读入10个数,然后输出这10个数,这就涉及了多个元素的操作。
我们再类比数列,假如我们要对数列$a_i$的第一项到第十项求和:
用的是不是$\sum_{i=1}^{10}a_i$这个公式,
用个$i$来代表第几项,然后$i=1\sim10$,把$a_i$累加起来。
类比到编程,同样用个i
来代表第几项,然后i=0~9
,把arr[i]
累加起来存到sum
里。
仍要注意到第一项是从0开始,所以是0~9!
- 对数组前十项求和
for (i=0; i<=9; i++) sum = sum + arr[i];
其中这里的涉及到从头到尾加起来的操作,
我们把对一个数组从头到尾进行某些操作叫做“遍历”。
以后会提到的概念注意一下。
那么类推一下,要向数组里读入$10$个数
- 读入十个数到数组前十项
for (i=0; i<=9; i++) cin >> arr[i];
然后再输出
- 输出数组中前十项
for (i=0; i<=9; i++) cout << arr[i] << " ";
总代码:
int i, arr[100], sum = 0;
cout << "请输入十个数:";
for (i = 0; i <= 9; i++)
cin >> arr[i];
for (i = 0; i <= 9; i++)
sum = sum + arr[i];
cout << "你刚才输入的十个数为:" << endl;
for (i = 0; i <= 9; i++)
cout << "arr[" << i << "] = " << arr[i] << endl;
cout << "总和为:" << sum;
如果为先输入一个数n
,然后读入n
个数,只需要改下循环条件即可。
- 读入n个数到数组
int n; cin >> n; for (i = 0; i <= n-1; i++) //注意读n个数是(i=0;i<=n-1),就像之前读10个数是(i=0;i<=9) //也可以写成 for (int i = 0; i < n; i++),不过最好选择一种格式以后就这样写,不然可能会晕 cin >> arr[i];
其余输出什么的同理。
3、对多个数组的运用
很多时候我们可能要从a
数组拿出一些数放到b
数组里,这个时候下标可能就会很疑惑。
比如我们可能会把arr
数组里十个数放到b
数组对应位置里。
这个时候数学表示就是$b_i=arr_i(i=1\sim10)$
- 把
arr
数组十个数放到b
数组里for (i=0; i<=9; i++) b[i] = arr[i];
但不一定每次都是刚好把arr
的第i项放到b
的第i项,也可能是比如:
从arr
的第五项开始,取5项(即a[4] ~ a[8]
,放到b
的第十项后面(即(b[9] ~ b[13]
)。
要记住数组的下标不只是用i
来表示,也可以用其他变量来表示。
因此我们可以定义两个变量j
和k
,来分别表示两个数组arr
和b
的下标。
刚开始令j = 4
,k = 9
开始取第一项放进b
时,也就是b[9] = arr[4]
,这个时候就是b[k] = arr[j]
。
然后取第二项放进b
时,也就是b[10] = arr[5]
,
因此我们就可以在放完一项后,让k = k + 1
和j = j + 1
,
这个时候的b[k] = arr[j]
,是不是就代表b[10] = arr[5]
了。
- 从
arr
的第五项开始,取5项,放到b
的第十项后面。j = 4, k = 9; //分别代表arr数组和b数组的下标 for (i=1; i<=5; i++) //做5次循环,代表取5项 { b[k] = arr[j]; k++; j++; }
这里是比较难但很重要的点,如果分析也看不懂,可以手动模拟一下:
自己按照程序一行一行执行,在本子上画两行表格,一行代表arr
数组,一行代表b
数组;j=4
时就用个箭头指向arr[4]
,j++则移动箭头指向arr[5]
……
如果理解了,那数组差不多也都理解了。
四、例题讲解
选择“实验8”的第1题。
1、题目要求
2、数组的定义分析
因为要输入的是实数(小数),所以要用double
或float
类型。
然后有15个数,但注意到要把计算后的平均值存到a
数组最后的a[15]
里,即实际上为16个数,长度为16。
故定义数组:
double a[16];
3、数组刚开始的原样读入、原样输出和求平均值
如果认真看了之前的“数组的运用”,这里应该问题不大。
多的点就是要每行五个输出,并且域宽为10。
代码:
double sum = 0; //求和变量注意清零 //读入部分 for (i = 0; i <= 14; i++) //i=0~14,读入十五个数 { cin >> a[i]; //读入a[i] sum = sum + a[i]; //顺便对a[i]的所有项求和,方便后面求平均值 } //求平均值部分 a[15] = sum / 15; //求的总和除以个数,也就算的是平均值,放到题上要求的a[15]里 //输出部分 for (i = 0; i <= 14; i++) { if ((i+1) % 5 == 0) cout << endl; //这里用如果(i+1)%5==0则换行,也就是i=5,10,15,...的时候换行,达成了每五个换行的效果 //这个可以记下来,如果是每7个换行,就写 if (i%7 == 0) cout<<endl; cout << setw(10) << a[i]; //输出a[i],setw为设置域宽 }
4、调整a数组,以满足题目条件形式输出
因为我们要调整a
数组里的数,最终输出a
数组。
所以可以先把a
数组里的所有数存到b
数组里,然后再“遍历”b
数组,判断某一个数b[i]
跟平均值的关系,如果大于则放到a
数组前面,小于则放到后面。
首先先来写怎么把a
数组里的所有数存到b
数组里,前面已经写过了这里直接写代码。
代码:
for (i = 0; i <= 14; i++) //把a数组放到b数组里 { b[i] = a[i]; }
接下来就是难点了,判断出关系后,怎么样才能把b[i]
放到a
数组前面或者后面。
之前说过的,下标不一定只能用i
,也可以定义新变量来表示下标。
于是我们可以定义两个变量
begin
和end
,分别代表a
数组前面和后面的下标。
刚开始begin = 0, end = 14
,分别代表最开始的前面的下标和后面的下标。
![]()
way_1
【注意a[15]
为平均值】
然后遍历
b
数组,假如第一个数b[i]
($i=1$)为$3$,小于平均值a[15]
则该放到后面,也就是a[end]
。
先让a[end]=b[i]
,
![]()
way_2
这样,当再次找到下个小于平均值的数时,则会放到当前的最后面处;
找到下个大于平均值的数时,则会放到当前的最前面处。
如图:![]()
way_4
- 代码:
cout << "调整后的数据为:" << endl; for (i = 0; i <= 14; i++) //把a数组放到b数组里 { b[i] = a[i]; } int begin = 0, end = 14; for (i = 0; i <= 14; i++) //遍历b数组,跟平均数比较,放回a数组 { if (b[i] < a[15]) //跟平均数比较 { a[end] = b[i]; end--; } else { a[begin] = b[i]; begin++; } } for (i = 0; i <= 14; i++) //输出a数组 { if (i % 5 == 0) cout << endl; cout << setw(10) << a[i]; }
5、总代码
#include <iomanip>
#include <iostream>
using namespace std;
int main()
{
int i;
double a[16], b[16];
double sum = 0.0;
cout << "请输入15个实型数:" << endl;
for (i = 0; i < 15; i++) //读入
{
cin >> a[i];
sum = sum + a[i];
}
a[15] = sum / 15; //求平均值
for (i = 0; i < 15; i++) //原样输出
{
if (i % 5 == 0 && i != 0) //【这里加了个i!=0的条件,防止最开始就换行
{
cout << endl;
}
cout << setw(10) << a[i];
}
cout << endl
<< "调整后的数据为:" << endl;
for (i = 0; i < 15; i++) //把a数组放到b数组里
{
b[i] = a[i];
}
int begin = 0, end = 14;
for (i = 0; i < 15; i++) //遍历b数组,跟平均数比较,放回a数组
{
if (b[i] < a[15])
{
a[end] = b[i];
end--;
}
else
{
a[begin] = b[i];
begin++;
}
}
for (i = 0; i < 16; i++) //输出a数组【注意这里是遍历输出整个a数组,即a[15]这个存的平均值也要输出,所以变成了(i = 0; i <16; i++)
{
if (i % 5 == 0 && i != 0)
cout << endl;
cout << setw(10) << a[i];
}
}
- 这里只讲的老师的第一种方法,更好理解一些。对于第二种方法可以自行尝试,跟这个大致相同,不懂也可以自己在草稿纸上模拟一下。
五、其他提示
-
数组的范围可以开大,但不能开小。
意思就是尽管最多可能只有10个整数,你可以定义为int a[100]
,但不可以int a[9]
。
推荐是比最多个数开稍微大一点,这样又可以偷懒想要开几个,又可以防止越界错误【本来只定义了15个,你访问了a[20]
】。 -
因为编程里数组第一项是从
a[0]
开始的,比较反人类x……
所以如果想按照数学习惯,完全可以从a[1]
开始存数。比如读入15个数,原来可能写成
for (i = 0; i <= 14; i++) cin >> a[i];
这样就是存在
a[0]~a[14]
里。你也可以写成符合我们习惯的
for (i = 1; i <= 15; i++) cin >> a[i];
这样就是存在
a[1]~a[15]
里。不过选择好一种自己喜欢的就这么写,不要一会从$0\sim14$一会又$1\sim15$,不然会很混乱。
-
没了。
-
有关排序的算法可能是常考点,各位可以自己去背一下。
以上。