第五单元数组总结
第一课一维数组的定义
格式:类型标识符 数组名[常量表达式];
注意:例如①int a[50];注意共有50个元素,它们的编号从0开始到49
②值必须在数组定义的下标范围内且只能逐个引用数组的单个元素
③数组大小必须是值为正数的常量不能为变量一旦定义不能改变大小
数组定义后的初值仍然是随机数一般要初始化
如何使两个数组值相等
第二课 一维数组的输入与输出
采用循环语句结合下标变化逐个元素进行输入输出
整体赋值的两个函数
①memset函数(头文件#include<cstring>)按字节进行赋值
例如 memset(h,0,sizeof(h); 就是将h数组所有元素均赋值为0
②fill函数(头文件#include<algorithm>)按元素进行赋值
例如 fill(a,a+10,5);a的前10个元素赋值为5
#include<iostream>
#include<cstring>
using namespace std;
int main(){
int a[10],b[10],c[10],d[10],i;
memset(a,0,sizeof(a)); // 将a数组所有元素均赋值为0
for(i = 0; i < 9; i++) cout << a[i] << “ “ ;
cout << a[9] << endl;
memset(b,1,sizeof(b));// 将 b 数组所有元素均赋值为
//二进制数 2^0+2^8+2^16+2^24=16843009 for(i = 0; i < 9; i++) cout << b[i] << “ “ ;
cout << b[9] << endl;
memset(c,0,5);
//将 c 数组前 5 个字节都赋值为 0,所以只能确定 c[0]
//等于0,其他元素值不确定
for(i = 0; i < 9; i++) cout << c[i] << “ “ ;
cout << c[9] << endl;
fill(d,d+5,8);
//将 d 数组前 5 个元素都赋值为 8,其他元素值不确定
for(i = 0; i < 9; i++) cout << d[i] << “ “ ;
cout << d[9] << endl;
return 0;
}
注意事项:memset一般赋值0不经常赋值别的数
例题 走楼梯
#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]);
printf( “ %d\n ” ,f[n]);
return 0;
}
本质 应用了斐波那契数列
原理f[i]=f[i-1]+f[i-2]
第三课 一维数组的插入删除
原理
主要应用于插队排队问题例题
【问题描述】
有 n 个人(每个人有一个唯一的编号,用 1~n 之间的整数表示)在一个水龙头前排队准备接水,现在第 n 个人有特殊情况,经过协商,大家允许他插队到第 x 个位置。输出第 n 个人插队后的排队情况。
【输入格式】
第一行 1 个正整数 n,表示有 n 个人,2<n≤100。
第二行包含 n 个正整数,之间用一个空格隔开,表示排在队伍中的第 1~ 第 n 个人的编号。
第三行包含 1 个正整数 x,表示第 n 个人插队的位置,1≤x<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]);
scanf( “ %d ” ,&x);
for(i = n; i >= x; i--) q[i+1] = q[i];
q[x] = q[n+1];
for(i = 1; i < n; i++) printf( “ %d “ ,q[i]);
printf( “ %d\n ” ,q[n]);
return 0;
}
第四课 一维数组的查找统计
常见算法顺序查找和二分查找
二分查找的前提数组中的元素都是有序的
例题 比身高
#include<cstdio>
using namespace std;
int h[1001],n,i,j,ans,t1,t2;
int main(){
scanf( “ %d ” ,&n);
for(i = 1; i <= n; i++) scanf( “ %d ” ,&h[i]);
for(i = 1; i <= n; i++){
t1 = t2 = 0;
for(j = 1; j < i; j+
+)
if(h[j] > h[i]) t1++;// 排在他前面且比他高的人数
for(j = i + 1; j <= n; j++)
if(h[j] > h[i]) t2++;// 排在他后面且比他高的人数
if(t1 == t2) ans++;
}
printf( “ %d\n ” ,ans);
return 0;
}
注意计数问题
局部计数与面相全局计数
局部一定要在具体统计之前赋初值
第五课 一维数组的元素排序
4种方式
选择排序 冒泡排序 插入排序 桶排序
桶排序方法
问题描述】
某商场的仓库中有 n 件商品,每件商品的价格在 0~1000 之间(价格为 0 的商品为赠品)。
现在商场经理要求将这 n 件商品按价格由低到高排序。请编程输出 n 件商品排序后的情况。
【输入格式】
第一行一个正整数 n,表示有 n 件商品,1≤n≤100000。
接下来的 n 行,每行一个整数,表示第 i 件商品的价格。
【输出格式】
n 行,每行输出一个整数
#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;
}
排序常用函数
sort函数
#include <algorithm>
using namespace std;
默认的sort函数是按升序排。
sort(a,a+n); //两个参数分别为待排序数组的首地址和尾地址
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
int a[10]={9,6,3,8,5,2,7,4,1,0};
for(int i=0;i<10;i++)
cout<<a[i]<<endl;
sort(a,a+10);
for(int i=0;i<10;i++)
cout<<a[i]<<endl;
return 0;
}
第六课 一维数组的应用举例
素数大酬宾的筛选法
相比穷举法,筛选法的效率更高。以求 1~20 之内素数为例,具体步骤如下:
(1) 将所有数(2~n)放入“筛子”中,把 1 删除;
(2) 2 在筛中,将 2 的倍数 2,4,…,20 删除(筛去);
(3) 3 在筛中,将 3 的倍数 6,9,…,18 删除(筛去);
(4) 4 不在筛中,不执行删除(筛去)操作
(10) 10 不在筛中,不执行删除(筛去)操作
#include<iostream>
#include<cmath>
using namespace std;
int main(){
int n,i,j;
bool p[100001];
for(i = 0; i <= 100000; i++) p[i] = true;
p[1] = false;
cin >> n;
cout << 2;
for(i = 2; i <= sqrt(n); i++)
if(p[i]) for(j = 2; i*j <= n; j++) p[i*j] = false;
for(i = 3; i <= n; i++) if(p[i]) cout << “ “ << i;
cout << endl;
return 0;
}
注意要学会进行预处理
第七课 二维数组的定义和操作
格式类型标识符 数组名[常量表达式1][常量表达式2]
注意事项同一维数组
主要应用于方阵问题
第八,九课 二维数组的应用举例及数字方阵
蛇形方阵
#include <stdio.h>
#include <string.h>
int main()
{
int x,y,i,j,k,sum,n;
int a[105][105];
x=y=1;
memset(a,0,sizeof(a));
scanf("%d",&n);
for (i=1;i<=n;i++)
for (j=1;j<=n+1-i;j++)
{
k=i+j-2;
sum=(k+1)*k/2;
if (k%2)//如果前面的对角线个数是奇数
a[i][j]=sum+i;
else
a[i][j]=sum+j;
}
for (i=1;i<=n;i++)
for (j=n-i+2;j<=n;j++)
a[i][j]=n*n+1-a[n+1-i][n+1-j];
for (i=1;i<=n;i++)
{
for (j=1;j<=n;j++)
printf("%5d",a[i][j]);
printf("\n");
}
return 0;
}
此类问题具有极强的规律性,需要我们善于结合数学思维发现规律,从而提高编译效率
第十课 字符数组
用字符常量逐个初始化:char letter[5]={'a','e','i','o','u'};
用赋值语句逐个元素赋值:letter[0]='a';…
用 scanf 读入整个数组:scanf ("%s",letter);
用 scanf 逐个元素读入:scanf ("%c",&letter[0]);…
用 cin 输入整个数组:cin >> letter;
用 cin 逐个元素输入:cin >> letter[0];…
用 gets 读入整个数组:gets(letter);
用 getchar 逐个读入:letter[0]=getchar();…
输出类似,注意逐个读入与整个所使用的格式
gets()读入时只写数组名且空格可被读入回车作为间隔符
区别scanf(空格,回车作为间隔符)
输入大量数据时尽量不要使用scanf效率很低
使用getchar(高效)
例题 数字和
体会高位数字如何存数
注意strlen函数的用法
补充函数
重难点
①矩阵问题如何利用数学思维找到更加优化的程序解决方案
②排序问题如何在多重循环中理清思路,以及考虑超不超时的问题
③在实际问题中如例题做游戏,扫雷等篇幅比较长的文字中提取关键词从而找到解决方案
④如何寻找更加快捷的函数解决问题
学习体会
①从简单的分支,顺序,到稍微复杂的循环,再到难度更大的数组问题让我体会到,如果想快速的解决问题不能只是依赖课本或者老师上课讲的内容,要不断学习新知识
②如果要想使程序更加优化,不能只是看到表面的那一个题要看的其蕴含的数学逻辑与规律这是需要我自己通过联系来提高的方面
③查错能力,做了数组之后自己得的奇怪的分数也多了有6分8分这说明还有的数据没有通过检验,这需要进行检验,以及周全的考虑问题,这也是需要提高的一方面
总之通过做题自己暴露的问题也变的多了,更需要自己不断提高思考问题的方式方法!