数组总结

本文详细介绍了C++中一维数组的概念、定义、初始化、引用、输入输出、元素操作以及常见问题的解决方案。通过示例,解释了一维数组在存储和操作数据方面的优势,包括斐波那契数列的实现、幸运数的判断、插队问题的解决、排序算法的演示等。此外,还探讨了二维数组和字符数组的基础知识。

一、一维数组的定义。

1.通过前面的学习可以编程完成一个这样一个任务,输入三名同学的身高并降序输出,但是如果将同学人数改成50人,仅用目前所学的知识编程就要定义50个简单变量,分别储存每名同学的身高,然后用cin语句输入50名同学的身高,显然这样的程序代码冗长繁琐,编程效率也很差,其实这个任务中50个变量是都是作用相同类型相同的变量,那么,他们可以集中在一起定义储存和操作。

为此是c++提供了数组类型。速度就是一组相同类型的变量,他们往往为了表示同一批对象的统一属性,如一个班级,所有同学的身高,全球所有国家的人口数等等,速度可以是一维的,也可以是二维的或多维的,在数学中可以用hi, i大于等于1小于等于50了,是第i个同学的身高i为编号。

在c++中,使用一维速度时,一般是从零开始编号,h[i]就表示i+1个同学的身高i为下标变量。读入50个同学的身高语句可以这样书写。

for(i=0;i<=49;i++)cin>>h[i];

2.一维数组的定义。

格式为

类型标识符  数组名[常量表达式];

其中类型表示符可以是任何基本数据类型,也可以是结构体等构造类型相同类型的数组可以一起定义。

数组名必须是合法的标识符,常量表达式的值记为速度元素的个数。

例如,int h[50];,又表示定义一个一维数组h共有50个元素,它们的编号从零开始到49,每个元素都是int型。

3.初始化

int a[5]={12,34,6,28,9};

int a[5]={0};

int a[]={11,22,33,44,55};

4.数组引用

数组名[下标]

从0算起最大n-1,表示安n个元素。

5.两个数组的值相等。

int i;

for(i=0;i<5;i++)

{

b(i)=a(i)

}

6.一维数组的元素引用。

数组定义好后,就可以引用数组中的任意一个元素,引用格式为"数组名[下标]"。其中下标只能为整形常量或整型表达式值必须在数组定义的下标范围内否则会出现下标越界错误.

7.一维数组的存储结构。

宿主在计算机内存单元中是连续储存的,程序,一旦执行到数组定义语句就会开辟出若干字节的内存单元。

二、一维数组的输入和输出

1.对速度的操作只能逐个引用单个元素,所以译为速度的输入输出等操作都是采用循环语句结合下标变化足够元素进行,例如输出一个速度可以写成:

int h[100];

for(i=0;i<100;i++)cout<<h[i];

2.那么批量数据一次性输入到一维数组中,一般有以下两种方法。

①键盘读入

如,

int h[100];

for(i=0;i<100;i++)cin>>h[i];

②直接赋值

如,

int h[100],a[20];

for(i=0;i<100;i++)h[i]=0;

for(i=0;i<20;i++)a[i]=i*2+1;

3.c++还提供了两个函数给数组整体复制。

①memset函数

该函数是给数组按元素进行赋值,一般是用在char型数组中,如果是int类型的数组,一般赋值为0和-1使用前包含头文件:#include<cstring>.

如,“memset(h,0,sizeof(h));”就是将h数组所有元素都赋值为0.

② fill函数

该函数是给数组按元素进行赋值,可以是整个数组,也可以是部分连续元素,可以付任何值,使用前包含头文件:#include<algorithm>

如,“fill(a,a+10,5);”就是将a数组的前10个元素赋值为5。

 

4.例题

①走楼梯

问题描述:一个楼梯有n及小苏同学从下往上走一步可以跨一级,也可以跨两级问他走到第N级楼梯有多少种走法?

输入格式:一行一个整数n,0<n<=30

输出格式:一行n个整数,之间用一个空格隔开,表示走到第1级,第2级,…第n级分别有多少种走法 。

问题分析:假设f(i)表示读到第二级楼梯的走法走走到第二i级(i>2)楼梯有两种,可能,一种是同地二,第i-i-1级走过来,另一种是从第i-2级的楼梯走过来。根据加法原理。f(i)=f(i-1)+f(i-2)边界条件为:f(1)=1,f(2)=2.具体实现时定义为数组f用赋值语句从前往后对数组的每一个元素逐个赋值,本质上f(i)构成了斐波那契序列。

#include<cstdio>

using namespace std;

int main(){

int n,i,f[31];

scanf("%d",&n);

f[1]=1;f[2]=2;

for(i=3;i<=n;i++)f[i]=f[i-1]+f[i-2];

for(i=1;i<n;i++)printf("%d",f[i]);

return 0;

}

②幸运数的划分

问题描述:判断一个正整数n是否能被一个幸运数整除。幸运数是指一个只包含四或七的正整数,如7,47,477等都是幸运数17,42都不是幸运数。

输入格式:一行一个正整数n,1<=n<=1000.

输出格式:一行一个字符串,如果能被幸运数整除,则输出yes,否则输出no。

问题分析:分析发现,1~1000范围内的幸运数只有14个。于是将这14个幸运数直接存储到一个数组lucky中,再穷举判断其中有没有一个数能整除n。

#include<cstdio>

using namespace std;

int main(){

int n,lucky[14]={4,7,44,47,74,77,444,447,474,477,744,747,774,777};//数组定义时给数组赋值

scanf("%d",&n);

bool flag=false;

for(int i=0;i<14;i++)

if(n%lucky[i]==0)flag=true;

if(flag)printf("YES\n");

else printf("NO\n");

return 0;

}

三、一维数组的插入删除

但实际应用中经常需要在速度中插入一个元素或者删除数组中的某一个元素,称为数组的插入操作或者删除操作,

插入一个元素,需要先找到插入位置,假设下标为x,将这个元素及其之后的所有元素依次往后移,一位注意要从后往前进行操作,再将给定的元素插入覆盖到位置x。

删除某一个元素,也是要先找到删除的位置,假设下标为x,将下标为x+1及其之后的所有元素依次向前移,一位覆盖原来位置上的元素。

插入或者先出一个区间连续若干个数,只要重复以上单个元素的操作即可,另外插入操作需要注意把数组的下标定义得足够大。

例题

①插队问题

问题描述:有嗯个人每个人有一为一个唯一的编号又一道恩之间的整数,表示在一个水龙头前排队准备接水,现在第n个人有特殊情况经过协商,大家允许他插队到第x位置输出第n个人插队后的排队情况。

输入格式:第一行一个正整数n,表示有n个人,n大于2小于等于100。

第二行包含n个正整数,直接用一个空格隔开,表示排在队伍中的第1~n个人的编号.

第三行包含一个正整数x表示第n个人插队的位置。1<=x<n

输出格式:一行包含n个正整数,之间用一个空格隔开,表示第n个人插队后的排队情况。

问题分析:N个人的排队情况可以用数组q[i]表示第i个位置上的人,定义数组时多定义一个位置,然后重复执行。q[i+1]=q[i],其中,i从n~x.最后在执行q[x]=q[n+1] ,输出q[1]~q[n]。

include<cstdio>

using namespace std;

int main(){

int n,i,x,q[102];

scanf("%d",&n);

for(i=1;i<=n;i++)scanf("%d",&q[i]);

acanf("%d",&x);

for(i=n;i>=n;i++)printf("%d",q[i]);

printf("%d\n",q[n]);

return 0;

}

四、一维数组的查找统计

一维数组的查找操作就是在一维数组中查找有没有某个元素,它的值等于指定的值x查找操作的结果可能是一个,也没找到找到一个或者找到很多个常见的查找算法,有顺序查找和二分查找顺序查找就是按照从前往后的顺序,将数组中的元素依次已与要查的数x进行比较,如果速度中的元素是有序的,递增或者递减,也可以采用二分查找二分查找,又称折半查找,其优点是比较次数少,查找速度快,假设数组a[n]是严格地方的,每个元素都是int型,现在要查找x这个元素,则二分查找的算法,则可以这样写。

int left=0,right=n-1;

int find=n;//find标记找到的位置,初始化为n,表示没找到

while(left<=right){

int mid=(left+right)/2;

if(a[mid]==x){//找到了,就标记位置,并退出循环

find=mid;

break;

}

if(x<a[mid])right=mid-1;//x只能在左半部分

if(a[mid]<x)left=mid+1;//x只能在右半部分

}

if(find!=n)printf("%d\n",find);

else peintf("not find\n");

例题

①比身高

问题描述:有N个人排成一排,假设他们的身高均为正整数,请找出其中符合以下条件的人:排在他前面且比它高的人数与排在他后面切比他高的人数相等。

输入格式:第一行为一个正整数N,1<N<1000,表示有多少人

下面N行,每行一个正整数表示从前往后每个人的身高,假设每个人的身高小于等于10000。

输出格式:一行一个整数表示满足这个条件的人数。

printf("%d\n",ans);

return 0;

}

五、一维数组的元素排序

排序就是按照某个关键字的大小将若干对象从小到大或者同大到小进行重新排列,关键字是对象的某一个属性,它可以是任何基本数据类型甚至结构体等。

例如,体育课上会按照身高从矮到高战队,这就是升序排列,身高是美国人的一个属性,也就是排序的关键字,再如将所有单词按照字典序倒过来排序,zoo,yes,most,key,computer,book,bad,apple等就是降序排序,关键字的类型就是字符串。

排序算法非常多,本课学习其中最基本的三种选择排序,冒泡排序和插入排序。它们本质上都是通过数组中的元素比较和交换来实现的,所以关键是速度下标的分析,本课结合一个其具体例子分解和讲解这三种算法。

1.站队

问题描述:给出n个同学的身高,请根据他们的身高收序排列并输出排序结果。

输入格式:第一行一个正整数n,表示有n个同学的身高,2<n<=100.

第二行,包括n个正整数之间,用一个空格隔开,表示n个同学的身高,每个同学的身高都在150到200cm之间。

输出格式:一行n个正整数,之间有一个空格隔开,表示n个同学表根据身高升序排列的结果。

问题分析:

①选择排序

选择排序的基本思想是,每一趟从待排序的数据中,通过打擂台比较出最小元素放在这些数据的最前面,这样第一趟把n个数中第一个到第n个最小的放在第一个位置,第二趟把剩余的n减一个数中,第二个到第n个最小的放在第二个位置,第三套把剩余的n-2个数中,第三个到第n个,最小的放在第三个位置。…第n减一烫,把剩下的两个数中第n减一个到第n个最小的放在第1n减一个位置,剩下的最后一个数第n个一定对大自然落在了第n个位置。

 ②冒泡排序

冒泡排序的基本思想是从第一个数开始,依次不断比较相邻的两个元素,如果逆序就交换这样一套排序结束后最大的元素就放在了第n个位置

③插入排序

插入排序的基本思想是把所有待排序元素分为前置后两段,前一段是已经排好序的后一段儿是大排序的,每一套都是把货一段的第一个数插入到前一段的某一个位置,保证前一段仍然是有序的。第一开始时第一个数作为前一段肯定是有序的,第一趟把第二个数插进去取保重前两个数游戏第二套把第三个数插进去,保证前三个有序…He嗯,减一趟把第n个数插入进去,保证n个数都有序。

六、一维数组的应用举例

①商品排序

问题描述:某商场的仓库中有n件产品,某件上每件产品的价格在零到1000之间,价格为零的商品为负赠品。现在商场经理要求这样做嗯件商品按价格由低到高排序,请编程输出n件商品排序后的情况。

输入格式:第一行一个正整数n,表示n件商品,1<=n<=100000

接下来的n行,每行一个整数表示第i件商品的价格。

输出格式:n行,每行输出一个整数。

问题分析:本题可以选用学过的任意一种排序算法实现,但是测试程序发现会超时,因为本题最多友谊10万件商品三种排序都需要两层循环嵌套。

其实分析数据发现一个重要特征数据虽然很多,但是数据范围比较小,这种情况下可以使用另外一种从排序算法—桶排序。

定义一个int型数组num[1001],num[x]记录整数x出现的次数,初始化都为0,每读到一个数x就执行num[x]=num[x]+1。输出时,从0~1000穷举x,每个x输出num[x]次。

#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;

}

②素数大酬宾

问题描述:某商场的仓库中有n种商品,每件商品按1~n依次编号,现在商场经理突发奇想决定将编号为素数(质数)的所有商品拿出来搞优惠酬宾活动,请编程帮助仓库管理员将编号为素数的商品选出来。

输入格式:一行一个正整数n,表示有n种商品,2<=n<=100000

输出格式:一行若干个正整数表示若干种商品编号,且每个编号均为素数,请从小到大输出每两个数之间有一个空格。

➊穷举法

➋筛选法

七、二维数组的定义和操作

1.二维数组的定义和初始化

①一般格式为

类型标识符 数组名[常量表达式1] [常量表达式2];

常量表达式一的值表示第一维大小常量表达式二的值表示第二维的大小材料表达式一和常量表达式二的成绩就是二维数组的元素个数,例如,

int h[4] [5];

表示数组h有4x5=20个元素,每个元素都是int型。

2.二维数组的存储及元素引用

因为二组二维数组本质上是以一维数组的,每一个元素又是一个一维数组,而计算机内部存储一维数组采用的是连续存储单元,所以二维数组的存储方式"行优先’的连续存储,先族逐个存储第0行上的所有元素,在逐个存储第一行上的所有元素,依此类推。

引诱二维数组的某一个元素格式为

数组名[下标1] [下标2]

例如,

cin>>h[3] [1];h[3] [1]*2;cout<<h[3] [1];

3.二维数组的输入输出

二维数组的输入输出操作也是针对每一个元素进行结合两个维度的下标变化用循环嵌套实现。

例题

①回型方阵

问题描述:输入一个正整数n,输出n*n的回型方阵。例如,n=5时输出:

11111

12221

12321

12221

11111

输入格式:一行一个正整数n,2<=n<=9。

输出格式:共n行,每行包含n个正整数,之间用一个空格隔开。

问题分析:

八、二维数组应用举例

例1

杨辉三角形

问题描述:输入正整数n输出杨辉三角形的前n行。

如,n=5,杨辉三角形如下,

1

11

121

1331

14641

输入格式:一行一个正整数n,1<=n<=20

输出格式:共n行,第i行包含i个正整数,之间用一个空格隔开。

 

九、数字方阵

数字方阵就是一个行列数相等的二维数组,其中的每个元素都是数字解决数字方阵问题一般有两种方法,解析法和模拟法。

解析法就是找出每一个方阵元素f[i][j]与i、j和数组规模嗯的通项公式,然后直接用两重循环给数组元素赋值相对比较容易,一般用在初始化等场合。

模拟法就是把数字方阵看成一个动态的填数过程吧,n*n的个数依次填入数组中,每填好一个数就定位好,下一个数的位置ii和j

例1 n阶奇数幻方

问题描述:行列式相等的矩阵称为方正把正整数1~n*n(n为奇数),排成一个n*n方阵,使得方阵中的每一行每一列以及两条对角线上的数之和都相等,这样的方阵称为n阶奇数,幻方编程输入n输出n阶的奇数幻方

 

十、字符数组

如果速度中的每个元素都是一个字符,这样的速度称为字符数组,有时把一维字符数组又称为字符串定义字符数组的方法与定义其他类型速度的方法类似。

需要注意的是在用scanf的%s格式或gets读入字符串时,会在字符串末尾自动添加一个空字符"\0"而是用getchar等方法读入字符串时,则要在字符串后手工加"\0"

本章例题

扫雷游戏地雷数

#include <iostream>

using namespace std;

const int M = 100;

const int N = 100;

char A[N][M];

int X[8] = {-1,-1,-1,0,1,1,1,0};//行坐标变化,从西北角开始

int Y[8] = {-1,0,1,1,1,0,-1,-1};//列坐标变化,从西北角开始

 

int main() 

{

int n, m, s, r, c;

cin >> n >> m;

for (int i=0; i<n; i++)

{

for (int j=0; j<m; j++)

{

cin >> A[i][j];

}

}

for (int i=0; i<n; i++)

{

for (int j=0; j<m; j++)

{

if (A[i][j] == '*')

cout << '*';

else

{

s = 0;

for (int k=0; k<8; k++)//累计周围地雷数量 

{

r = i+X[k];

c = j+Y[k];

s += (r>=0 && r<n && c>=0 && c<m && A[r][c]=='*');

}

cout << s;

}

}

cout << endl;

}

 

return 0;

我的感受:学到数组,发现数组上升了一个阶层更有难度。发现一个题的做法不止一种,可以有好多种。需要我们的灵活运用。分析题意时要从整体把握又要分到各个细节。

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值