对数组的认识
如果有一堆数据需要处理,在程序中可能需要定义很多的变量,这样可以定义一个数组,相当于a1,a2.....,an,这样就可以定义很多的数,进行同种类型数的处理,数组可以分为一维数组,二维数组,多维数组。
一维数组
按顺序排列的一组同种类型的变量构成的集合。
定义
数据类型 数据名 [整数1] [整数2]……[整数n]
例如:int a[5]
可以想象成一个单坐标轴,不同的点是一个存储单元,你可以存储信息,可以是数或字符,可以进行大量的数据处理,免于定义的麻烦。
注意:下标不能越界。
输入输出
一维数组的输入,输出等操作,都是通过循环语句结合下标变化,逐个元素进行的。
例如:for(int i=0;i<n;i++)cin>>a[i];
for(int i=0;i<n;i++)cout>>a[i];
此外C++还提供了两种整体赋值的函数
memset函数
给数组“按字节”赋值,一般用在char型数组中,如果是int型的数组,一般赋值为0和-1,使用前需要包含头文件:#include<cstring>。
fill函数
给数组“按元素”赋值,可以是整个数组,也可以是部分连续元素,可以赋任何值。使用前需要包含头文件:#include <algorithm>。
插入删除
插入元素,首先找到插入位置,将此位置元素及之后的元素往后移一位,再把要插入的元素覆盖在原来的位置上。
删除元素,首先找到删除的位置,将此位置之后的元素往前移一位,覆盖原来的元素。
查找统计
一维数组的查找就是在一维数组中查找有没有某个元素,使它的值等于一个指定的值。
常见的查找方法有“顺序”查找和“二分”查找。
元素排序
“排序”就是按照某个关键字的大小,将若干对象从小到大或者从大到小进行重新排列。关键字是对象的某一个属性,它可以是任何基本数据类型,甚至结构体等。C++sort函数
#include <algorithm>
using namespace std;
默认的sort函数是按升序排。
sort(a,a+n); //两个参数分别为待排序数组的首地址和尾地址
应用举例
商品排序
【问题描述】
某商场的仓库中有 n 件商品,每件商品的价格在 0~1000 之间(价格为 0 的商品为赠品)。
现在商场经理要求将这 n 件商品按价格由低到高排序。请编程输出 n 件商品排序后的情况。
【输入格式】
第一行一个正整数 n,表示有 n 件商品,1≤n≤100000。
接下来的 n 行,每行一个整数,表示第 i 件商品的价格。
【输出格式】
n 行,每行输出一个整数。
【输入样例】
5
1
8
1
2
2
【输出样例】
1
1
2
2
8
【问题分析】
本题可以选用学过的任意一种排序算法实现,但是测试程序发现会“超时”,因为本题最多有 100000 件商品,三种排序都需要两层循环嵌套。
其实,分析数据发现一个重要特征:数据虽然很多,但是数据范围比较小。这种情况下,可以使用另外一种排序算法——桶排序。定义一个 int 型数组 num[1001],num[x]记录整数 x 出现的次数,初始化都为 0,每读到一个数 x,就执行 num[x] = num[x]+1。输出时,从 0 ~ 1000 穷举 x,每个 x 输出 num[x]次。
//p5-6-2,桶排序
#include<iostream>
using namespace std;
int n,i,j,number,num[1001];
int main(){
cin >> n;
for(i = 1; i <= n; i++){
cin >> number;
num[number]++;// 记录整数 number 出现的次数
}
for(i = 0; i < 1001; i++)
for(j = 1; j <= num[i]; j++)
cout << i <<endl;// 输出 num[i] 次 i
return 0;
}
二维数组
一维数组的每一个元素又是一个一维数组,这样的数组称为二维数组。
定义操作
定义二维数组的一般格式为:类型标识符 数组名 [ 常量表达式 1][ 常量表达式 2];常量表达式 1 的值表示第一维大小,常量表达式 2 的值表示第二维大小,常量表达式 1 和常量表达式 2 的乘积就是二维数组的元素个数。
输入输出
二维数组的输入、输出操作也是针对每一个元素进行,结合两个维度的下标变化,用循环嵌套实现。
应用举例
杨辉三角形
【问题描述】
输入正整数 n,输出杨辉三角形的前 n 行。例如,n=5 时,杨辉三角形如下:
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
【输入格式】
一行一个正整数 n,1≤n≤20。
【输出格式】
共 n 行,第 i 行包含 i 个正整数,之间用一个空格隔开。
【输入样例】
5
【输出样例】
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
【问题分析】
定义一个二维数组 tri 存储杨辉三角形(其实只用到二维数组的左下部分)。对于第 i 行(1≤i≤n),共有 i 个数,其中第一个数和最后一个数都是 1,其他数 tri[i][j] = tri[i-1][j-1] + tri[i-1][j]。具体实现,采用“递推法”,逐行逐列给每个数组元素赋值。
#include <stdio.h>
int is(int,int);//输出数字
int main()
{
int m,n;
scanf("%d",&m);
for(int z=1;z<=m;z++)//分别输出行数和列数
{
for (n=1;n<=z;n++)
{
if(n<z)
printf("%d ",is(z,n));
else
printf("%d",is(z,n));
}
printf("\n");
}
}
int is(int m,int n)//
{
int s;
if(n==1||n==m||m==1)//当三角的前两行和在三角直角边和斜角边都输出1
s=1;
else
{
s=is(m-1,n-1)+is(m-1,n);//这是递归函数
}
return s;
}
数字方阵
数字方阵就是一个行列数相等的二维数组,其中的每个元素都是数字。解决数字方阵问题,一般有两种方法:解析法和模拟法。解析法就是找出每一个方阵元素 f [i][j] 与 i、j 和数组规模n的通项公式,然后直接用两重循环给数组元素赋值,相对比较容易,一般用在初始化等场合。模拟法就是把数字方阵看成一个动态的填数过程,把 n^2 个数依次填入数组中,每填好一个数,就定位好下一个数的位置 i 和 j。
【问题描述】
用数字1,2,3,4,...,n*n这n2个数蛇形填充规模为n*n的方阵。
蛇形填充方法为:
对于每一条左下-右上的斜线,从左上到右下依次编号1,2,...,2n-1;按编号从小到大的顺序,将数字从小到大填入各条斜线,其中编号为奇数的从左下向右上填写,编号为偶数的从右上到左下填写。
比如n=4时,方阵填充为如下形式:
1 2 6 7
3 5 8 13
4 9 12 14
10 11 15 16
【输入】
输入一个不大于10的正整数n,表示方阵的行数。
【输出】
输出该方阵,相邻两个元素之间用单个空格间隔。
【样例输入】
4
【样例输出】
1 2 6 7
3 5 8 13
4 9 12 14
10 11 15 16
#include<cstdio>
int t=1,a[15][15];
int main(){
int n,i,j;
scanf("%d",&n);
i=j=1;//初始位置
while(t<=n*n){//没有遍历完继续
while(1){//向右上走
if(i<1||j>n){//不出界
i++;j--;break;
}
else{
a[i][j]=t;t++;i--;j++;
}
}
if(j==n) i++;
else if(i==1) j++;
while(1){//向左下走
if(i>n||j<1){//不出界
j++;i--;break;
}
else{
a[i][j]=t;t++;i++;j--;
}
}
if(i==n) j++;
else if(j==1) i++;
}
for(i=1;i<=n;i++){
for(j=1;j<n;j++)
printf("%d ",a[i][j]);
printf("%d\n",a[i][n]);
}
}
字符数组
数组中的每个元素都是一个字符的数组称为“字符数组”。有时,把一维字符数组又称为“字符串”。
收获
数组为我们提供了一个可以同时处理大量数据的方法,在处理大量数据时,免去了定义的麻烦;而二维数组则近似地和坐标系联系了起来,处理的问题也扩大到平面几何的程度,其中的数字方阵更是和现在学习的代数里的方阵一样,可以用C++来解决一些实际的代数方阵问题。使用数组,我们可以很容易的将一组数据重新排序,也可以很容易的从一组数据中筛选出自己所需要的元素。
感想
对数组,我只有这一个感想——难。原本以为循环结构已经不简单了,可我还是太天真了,数组比起循环,变态的有过之而无不及。我就感觉我是不是不适合学习C++?是不是学不会C++?目前的情况看来,如果考试出的题和数组这部分的一些题一样的难度,那我估计是跑不了挂科了。就只希望老师能动恻隐之心,别出过于难的题。但是,另一方面,正是难,才给了我上进的动力,才使我发现自身的不足,才会使我不断提高。