一维数组
- 数组相当于一个容器,开一个连续的空间,将所需要的数据储存起来,同时可以通过下标引用
- 数组名代表数组名称,同时代表了数组首位置,因此,不能通过将数组名复制到另一个数组
- 数组内的所有变量的类型都是相一致的
- 数组定义时元素的总个数只能用常量定义,包括常量和符号常量,但是变量是不合法的
- int a[10]; //数组定义是合法的 int b[n]; //数组定义是非法的
- 数组引用 下标可以是任意值为整型的表达式,下标可以是变量,引用时只能逐个引用,不能一次引用一个数组 memset(a,0,sizeof(a))将数组中的元素全部赋值为0,或者为-1,头文件为cstring
- 初始化 可以全部列举出来,也可以写一部分,全局变量初始化为0;但是局部变量没有初始化,给的都是随机数
- 数组越界 下标值为整数,从0开始,若下标为负或者大于元素个数,语法都是正确的,但数组元素不在数组的储存空间,造成内存混乱
- 应用 开数组时将数组在全局变量中定义,数组可以开的很大,并且数组所有元素初始化为0 从数组a复制k个元素到数组b,可以memcpy(b,a,sizeof(int)*k)也可以定义不同的类型,头文件为cstring
二维数组
- 二维数组和一维数组的定义,引用,初始化都相似,二维数组和一维数组在计算机中所开的空间是一样的
- 二维数组也是数组的数组,同样,当下标有多个时,可以定义多维数组,应用和二维数组相似
- 二维数组引用时必须给出两个下标,每个下标的取值不能超过指定范围,否则导致越界错误
- 初始化可以将每一行分开写在括号里,也可以把所有数据写在一个括号里 ,数据赋值时先排行排列
- 二维数组和矩阵相似,从而可以计算矩阵的转置,交换行,加法和乘法的运算
字符类型和字符数组
- 无论数组的下标有几个,数组中的元素的类型必须相同,类型可以是任意类型,是字符型时,我们称它为字符数组
- 字符类型有常量和字符变量,定义使用单引号引起来,字符类型是一个有序数列,从而可以利用字符变量,作为循环变量使用
- 元素为字符的数组为字符数组,可以存放字符序列和字符串,同时也有一维二维和三维之分
- 赋值分为初始化和元素的赋值,可以用字符初始化也可以用字符串初始化,字符用单引号引起来,字符串用双引号引起来,并且有结束符\0
- 字符串中,结束符占用一个字节,因此字符串常量占用字节数等于字符串的字节数加1
- 可以把字符常量赋给字符变量,但不能把字符串常量赋给字符串变量
- 输入输出 键盘输入字符数组可以使用scanf语句和gets语句
- 输入字符串时,不用加取地址符,系统自动加上结束符
- scanf语句不能读取回车键和空格键,gets只能输入一个字符串,可以读取一行
- 输出字符串可以使用printf语句和puts语句
- printf语句输出字符串不包括结束符,puts语句一个字符串和一个换行符
典型例题
1.约瑟夫问题(n个人围成圈报数,猴子选大王,持密码报数,狐狸追兔子)
设置一个标记数组,一个人有两种状态,出圈和未出圈;数到最后一个人,再到第一个人;当所有人都出圈,停止,也就是出圈的人数有n个人,停止
for(i=1;i<=n;i++)
a[i]=false;
f=0,t=0,s=0;
while(f!=n)
{
++t;
if(t==n+1)t=1;
if(a[t]==false)++s;
if(s==m)
{
s=0;
cout<<t<<" ";
a[t]=true;
++f;
}
}
大多数题用到标记数组,或者标记变量,使用标记变量可以是许多问题变得更简单
标记变量:有趣的跳跃,计算鞍点,寻找配对数
标记数组:校门外的树,开关门问题,开关灯问题
2.排序问题(选择排序,冒泡排序,插入排序,桶排序)
sort(a,a+n)前闭后开,默认从小到大排序,也可以自定义函数完成其他排序,头文件algorithm
选择排序:每一次选出一个最小的数,下一次再从剩余数中选出最小的,以此类推,完成排序
冒泡排序:每一次将最大的数排到后面,再将前面的数重复操作,完成从小到大排序
插入排序:在一个有序的数列,和中间的数比较,找到一个合适的位置插入,取中间数,即为二分法。
如果是无序数列,但在这个数列中总有一个数是有序的,以这个数为有序数列,将其它的数插入,完成排序
桶排序:开一个较大的数组,将数组清零,如果数据中出现了该数,所对下标的数加加,最后按数组输出即可
例题:有趣的跳跃用到排序,倒置排序(可以开两个数组,两个数组一起进行变化)
寻找配对数问题优化(排序,折半查找,预处理)
将所给的数据排序,预处理用数组存起来,两个循环嵌套,将两个数的乘积在预处理的数组中折半查找,判断是否存在
3.筛法,预处理找素数,完全平方数
for(i=2;i<=n;i++)
a[i]=1;
for(i=2;i<=sqrt(n);i++)
if(a[i])
for(j=2;j<=n/i;j++)
a[i*j]=0;
4.与矩阵有关的问题
矩阵也就是二维数组,有简单的问题,例如,交换两行两列的数据,转置,交换行列,求某行,列数据的和
例题:变换的矩阵,矩阵交换行,蛇形填充数组,计算鞍点等
5.字符数组
scanf输入时,不能加取地址符,不能读取空格
统计单词个数,可以通过空格来简单计算,和将单词首字母换成大写方法一样
大小写转化,数值相差32,通过32转化即可,也可以用字符处理函数(strlwr 大写换小写 strupr 小写换大写)
例题:反反复复,字符串hash
6.对数组内周期赋值
石头剪刀布(周期为m,总数为n,已知第一个周期内的数值)
for(i=1;i<=m;i++)
for(j=m+1;j<=n;j+=m)
a[j]=a[i];
7.相似类型题
扫雷,细菌的繁殖与扩散
注意题意分析,通过一个量确定另一个量的变化,分析好哪一个量,梳理好逻辑关系
总结
课程已经学了很多了,感觉程序写起来也简单也难,写出一个程序并且编译成功很简单,但是要输出相应的结果很难,这也是一个思维的锻炼,往往我们缺少的就是这样的锻炼。参加了acm新生赛,发现自己学的也就只是冰山一角,看见一个题,对它题意的分析,理解不到位,并且容易忽略了时间复杂度,出现超时现象,或者是定义的量太小。各种毛病都出现了,从而提醒了我要更加努力的学习,多分析题,而不是单单停留在会做一道题,要学会扩展,深入理解一道题,而不是只看表面。我会更加努力去学习,期待19周上机,希望那时候的我会比现在更优秀!!