数组的学习与使用

数组
数组的引入:
我们引入数组的目的是为了处理更多的数据,处理更加复杂的问题。
处理更多的数据就让我们联想到输入输出数据,当输入输出多组数据时,可以用之前学过的cin>>…,cout<<…;scanf(),printf();来解决,但是数据多了,就会暴露繁冗不便的弊端,于是我们就引入了数组。数组又分为一维数组,二维数组,字符数组等多种形式。

对于一维数组:
数组的定义要声明在main函数之外,那样数组才能开得很大,如果在main函数之内,数组稍大就会异常退出。
其定义格式为:类型标识符 数组名[常量表达式]
其数组名命名规则须与变量名一致,常量表达式表示数组元素的个数,绝对不能是变量。 数组的初始化在定义时可以一起完成:
格式:类型标识符 数组名[常量表达式]={值1,值2…},可以通过此方式对数组全部赋值,也可以赋值部分,值1,值2…代表先赋值前面的储存单元,依次类推。如果对数组所有元素均赋值为0,可简写为:{}。

需要注意的是下标范围,不能越界,储存元素从第一个储存单位开始储存,例:int a[10];
第一个储存单位为a[0],最后一个储存单位为a[9],a[10]不属于该数组的空间范围,超出数组储存单位(越界)的储存元素未知。
当下标在数组定义范围内时,下标可以为任意值为整型的表达式,该表达式里可以包含变量和函数调用,通过对数组下标变量的处理来对数组元素进行调试处理,数组元素可以像同类型的普通变量那样使用,对其进行赋值、运算等操作。

数组一般与循环结构结合使用,掌握好数组与循环结构的结合才能让我们更好地解决问题。例如写入5组数据,可以结合循环结构:
for(int i = 1;i<=5;i++)
cin>>a[i];

当然数组的使用也是有限制的,C++语言中只能逐个引用数组元素,而不能一次引用整个数组,例如:int a[100],b[100],a=b;这样的写法是非法的。如果要从数组a中复制k个元素到b组中,可以引用:memcpy(b,a,sizeof(int)*k),当然(int)随元素的数据类型而改变,如果是浮点数,写为(double)。如果把数组a中的元素全部复制到数组b中,可使用memcpy(b,a,sizeof(a))。使用memcpy函数要包含在头文件cstring中。

对于二维数组:
一维数组可以表示一行,那么二维数组便可以表示一个面,即行与列。
其一般格式为:
数据类型 数组名[常量表达式1][常量表达式2]
例int a[10][10];
其实质为10*10的正方形表格,可储存100个元素,其中第一个下标表示行数,第二个下标表示列数,即第一行第一列表示为a[0][0],第m行n列表示为a[m-1][n-1]。

二维数组的初始化:与一维数组类似,可以将每一行分开写在各自的括号里,也可以把所有的数据写到一个括号里,但是并不提倡这种做法,因为数据太多出错率高且不易检查。

对于多维数组:
其定义格式及其下标注释可参考一维数组,二维数组定义格式。

对于字符数组:
字符数组是指元素为字符的数组,用来存放字符序列或字符串。
字符与字符串几点区别:
字符串有一个结束符(‘ ’),因此字符串常量所占的字节数等于字符串所占字节数加1。
字符常量由单引号括起来,字符串常量由双引号括起来。
字符常量只能是单个字符,字符串常量可以是多个字符。
字符常量可以赋值给字符串常量,反之则不行。

字符串使用时,需要注意其输入输出形式:
输入: scanf(“%s”,字符串名称);不可加取地址符&,输入多个字符串时,以空格隔开。当然如果遇到需要输入一行字符串时,可以考虑使用gets(字符串名称);但是gets只能输入一个字符串,不像scanf以读取空格为结束,而是以读取到换行符为结束。两者各有优点,依情况选取使用。
输出:输出时可使用puts(字符串名称);来输出 ,输出一个字符串和一个换行符,例puts(a)等价于printf(“%s ”,a)。

对于数组的使用,在一维数组上可用于多数据的输入输出,排序等;在二维数组上我们也可以研究一些平面上的问题,计算鞍点,处理矩形,甚至可以做贪吃蛇、扫雷等二维平面小游戏。
举几个经典的例子:
一、排序问题,可以分为冒泡排序,插入排序,选择排序等。
冒泡排序:

for (int i=1; i<=n; ++i) cin>>a[i];                       //输入数值
     for (int j=1; j<=n-1; ++j)			//冒泡法排序
     for (int i=1; i<=n-j; ++i)  //两两相比较           
            if (a[i]<a[i+1])            //比较与交换
            {t=a[i]; a[i]=a[i+1]; a[i+1]=t;}     //也可以使用swap(a[i],a[i+1])来交换
     for (int i=1; i<=n; ++i)               
               cout<<setw(5)<<a[i];                   //输出排序后的数

函数排序:如果是从小到大按顺序排也可以使用函数sort();需要包含在头文件#include 库中,sort(a,a+n); //两个参数分别为待排序数组的首地址和尾地址。
倒置排序:

while(b!=0)
{ s=s*10+b%10;
 b/=10;}             //利用此段将数字倒置,例1234变为4321.

二、对于二维数组的使用,解决数学问题依然要了解公式或者寻求规律:
例如:正方形与长方形数量问题:
描述
设有一个n*m方格的棋盘(1≤m,n≤100)。
求出该棋盘中包含多少个正方形、多少个长方形(不包括正方形)。
例如:当n=2,m=3时
正方形的个数有8个;

即边长为1的正方形有6个;

边长为2的正方形有2个。
长方形的个数有10个
即21的长方形有4个
1
2的长方形有3个
31的长方形有2个
3
2的长方形有1个
借用公式:

#include<iostream>
using namespace std;
int main()
{
    int n,m,i,x=0,y;
	cin>>n>>m;
	for(i=1;i<=n&&i<=m;i++)
	x+=(n-i+1)*(m-i+1);
	y=(n+1)*(m+1)*n*m/4;
	cout<<x<<","<<y-x<<endl;
	return 0;
}

寻求规律:

#include<iostream>
#include<cstdio>
using namespace std;
int main()
{
    int a[100],b[100];
    int n,m,g=0,h=0;
    cin>>n>>m;
    for(int i=0;i<n;i++) a[i]=i;
    for(int j=0;j<m;j++) b[j]=j;
    for(int c=0;c<n;c++)
    {for(int d=0;d<n;d++)
    {for(int e=0;e<m;e++)
    {for(int f=0;f<m;f++)
    {
        if(a[c]-a[d]==b[e]-b[f]&&c<=d&&e<=f) g++;
        if(a[c]-a[d]!=b[e]-b[f]&&c<=d&&e<=f) h++;
    }}}}
    cout<<g<<","<<h;
    return 0;
	}

相对来说,还是公式法简单一些,运行起来节约时间。很多东西都是需要我们寻求规律并结合公式来写代码的。
感悟:
学完数组之后依然觉得数学思维的重要性,很多东西都是来找规律的,不同的规律,不同的想法编写的代码有难有易,运行起来也有所不同。
例如:求最大公约数,可以一个个来试,也可以通过辗转相除(欧几里得算法)来解决;查找数据,可以逐个查找,也可以通过折半(二分法)来查找;排序问题更可以用冒泡排序来解决等。
好的规律,好的方法都可以更快更简便的解决问题,我们现在解决问题的关键也是来找到规律,发现规律,很多时候写代码卡住的地方都是卡在了不知道怎么解决问题,不懂得其中的规律。这也是以后要加强学习的地方。

原文地址:https://www.cnblogs.com/study-hard-forever/p/12130086.html