2019-12-24

第五单元 数组
一.维数组的定义
数组的概念
按顺序排列的一组同种类型的变量构成的集合。
一个数组在内存中占一片连续的存储单元
1一维数组的定义
定义一维数组的格式:
类型标识符 数组名[常量表达式];
例:
int d[50],g[100]
int a[5*10]
#define N 50
int b[N]
下标从0开始
一维元素的引用
引用格式为 数组名[下标]
下标只能为整型常量或整型表达式,值必须在数组定义的下标范围内,否则会出现下标越界错误!
二.一维数组的输入与输出
输出数组:
int h[100];
for(i=0;i<100;i++) cout<<h[i];
输入数组:
1.键盘读入
int h[100];
for(i=0;i<100;i++) cin>>h[i];
2.直接赋值
int h[100],a[20];
for(i=0;i<100;i++) h[i]=0;
(1)memset 函数(清零作用)
给数组“按字节”进行赋值,一般用在 char 型数组中,如果是 int 类型的数组,一般赋值为 0 和 -1。使用前需要包含头文件:#include 。
(2)fill 函数
给数组“按元素”进行赋值,可以是整个数组,也可以是部分连续元素,可以赋任何值。使用前需要包含头文件:#include
例fill(a,a+10,5)就是将a数组的前10个元素赋值为5
int a[10]={0,1,2,3,4,5,6,7,8,9}
int a[10]={0,1,2,3,4}//部分赋值,后面的元素自动初始化为0
int a[ ]={1,2,3,4,5}//不定义数组长度,直接根据赋值个数定
#include
#include
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 数组所有元素均赋值为
//二进制数 20+28+216+224=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;
}
三.一维数组的插入删除
1.插入
插入一个元素,需要先找到插入的位置(假设下标为 x),将这个元素及其之后的所有元素依次往后移一位(注意要从后往前进行操作),再将给定的元素插入(覆盖)到位置 x
2.删除
删除某一个元素,也需要先找到删除的位置(假设下标为 x),将下标为 x+1 及其之后的所有元素依次向前移一位,覆盖原来位置上的元素
例2.
【问题描述】
有 n 个人(每个人有一个唯一的编号,用 1~n 之间的整数表示)在一个水龙头前排队准备接水,现在第 x 个人有特殊情况离开了队伍,求第 x 个人离开队伍后的排队情况。
【输入格式】
第一行 1 个正整数 n,表示有 n 个人,2<n≤100。
第二行包含n个正整数,之间用一个空格隔开,表示排在队伍中的第1个到第n个人的编号。
第三行包含 1 个正整数 x,表示第 x 个人离开队伍,1≤x≤n。
【输出格式】
一行包含 n-1 个正整数,之间用一个空格隔开,表示第 x 个人离开队伍后的排队情况。
【输入样例】
7
7 2 3 4 5 6 1
3
【输出样例】
7 2 4 5 6 1
#include
using namespace std;
四.一维数组的查找统计
1.顺序查找
顺序查找就是按照从前往后的顺序,将数组中的元素依次与要查找的数 x 进行比较。
2.二分查找
二分查找又称“折半”查找,其优点是比较次数少、查找速度快。但是要求数据是递增或递减排序的。
int left = 0,right = n-1;
int find =n;//find标记找到的位置,初始化为n,表示没找到
while(left <= right){
int mid s (left + right)/2;
if(a[mid] =x)(//找到了,就标记位置,并退出循环
find = mid;
break;
)
if(x< a[mid])right =mid-1;//x只能在左半部分
if (a[mid]<x)left = mld +1;1//x只能在右半部分
)
if(find != n) printf("%d\n",find);
else printf(“not find\n”);
五.一维数组的元素排序
求n个数中的最大值,并记录在数组中的位置
选择排序
main(){
int a[100000];
int i,j,max,l;
cin>>n;
for(i=0;i<n;i++) cin>> a[i];
for(j=0;j<n-1;j++)

{ l=j;
for(i=1;i<n;i++)
if(a[l]<a[i])
l=I;
if(l!=j) i=a[l],a[l]=a[j],a[j]=i;
}
return 0;
}
插入排序
void insSort(int a,int num)
{
for(i=1;i<num;i++)
{
l= i-1;temp=a[i];
while(l>=0&&a[l]>temp)
{
a[l+1]=a[l];
l–;
}
a[l+1]=temp;
}
}
冒泡排序
#include
 #include
 using namespace std;
 const int n=10;
 int t,a[n+1]; //定义数组
 int main()
 {
  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;}
  for (int i=1; i<=n; ++i)
cout<<setw(5)<<a[i]; //输出排序后的十个数
  cout<<endl;
  return 0;
 }
sort函数用法
#include
using namespace std;
默认的sort函数是按升序排。
sort(a,a+n); //两个参数分别为待排序数组的首地址和尾地址
六.一维数组的应用举例
【问题描述】
某商场的仓库中有 n 种商品,每件商品按 1~n 依次编号。现在商场经理突发奇想,决定将编号为素数(质数)的所有商品拿出来搞优惠酬宾活动。请编程帮助仓库管理员将编号为素数的商品选出来。
【输入格式】
一行一个正整数 n,表示有 n 种商品,2≤n≤100000。
【输出格式】
一行若干个正整数,表示若干种商品编号且每个编号均为素数,请从小到大输出,每两个数之间有一个空格。
【输入样例】
20
【输出样例】
2 3 5 7 11 13 17 19
【问题分析】
算法1、穷举法
穷举商品编号 2~n,判断每个编号是否为素数。这种方法效率不高,一旦 n 过大,程序就会超时。
//p5-6-3a
#include
#include
using namespace std;
int main(){
int n,i,j; bool flag;
cin >> n;
cout << 2;
for(i = 3; i <= n; i++){
flag = true;
for(j = 2; j <= sqrt(i); j++)
if(i % j == 0){flag = false;break;}
if(flag) cout << “ “ << i;
}
cout << endl;
return 0;
}
算法2、筛选法
筛选法又称为筛法,是由希腊著名数学家埃拉托色尼 (Eratosthenes) 提出的。相比穷举法,筛选法的效率更高。以求 1~20 之内素数为例,具体步骤如下:
(1) 将所有数(2~n)放入“筛子”中,把 1 删除;
(2) 2 在筛中,将 2 的倍数 2,4,…,20 删除(筛去);
(3) 3 在筛中,将 3 的倍数 6,9,…,18 删除(筛去);
(4) 4 不在筛中,不执行删除(筛去)操作;
……
(10) 10 不在筛中,不执行删除(筛去)操作。
#include
#include
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[ij] = false;
for(i = 3; i <= n; i++) if(p[i]) cout << “ “ << i;
cout << endl;
return 0;
}
七.二维数组的定义和操作
1.二维数组的定义和初始化
定义二维数组的一般格式为:
类型标识符 数组名 [ 常量表达式 1][ 常量表达式 2];
常量表达式 1 的值表示第一维大小,常量表达式 2 的值表示第二维大小,常量表达式 1 和常量表达式 2 的乘积就是二维数组的元素个数
2.二维数组的存储及元素引用
存储方式是行优先的连续存储,先逐个存储第0行上的元素,再逐个存储第一行,以此类推。
数组名[下标1][下标2]
3.二维数组的输入与输出

【问题描述】
输入一个正整数 n,输出 n×n 的回型方阵。例如,n=5 时,输出:
1 1 1 1 1
1 2 2 2 1
1 2 3 2 1
1 2 2 2 1
1 1 1 1 1
【输入格式】
一行一个正整数 n,2≤n≤9。
【输出格式】
共 n 行,每行包含 n 个正整数,之间用一个空格隔开
【输入样例】
5
【输出样例】
1 1 1 1 1
1 2 2 2 1
1 2 3 2 1
1 2 2 2 1
1 1 1 1 1
#include
using namespace std;
int n,i,j,k,mi,ma,a[10][10];
int main(){
cin >> n;
for(i = 1; i <= (n+1)/2; i++)
for(j = 1; j <= (n+1)/2; j++){
a[i][j] = min(i,j);
a[i][n+1-j]=a[n+1-i][j]=a[n+1-i][n+1-j]=a[i][j];
}
for(i = 1; i <= n; i++){
for(j = 1; j <= n-1; j++){
cout << a[i][j] << “ “ ;
}
cout << a[i][n] << endl;
}
return 0;
}
八.二维数组应用举例
【问题描述】
输入正整数 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<iostream>
#include<cstring>
#include
using nameapace std;
int n,i,j,tr1[21][21];
int main(){
cin >>n;
for(i= 1;i<= n;i++){
tri[i][1]=1;
tri[i][i]=1;
for(j=2;j<1;5++)
tri[i][j]=tri(i-1][5-1]+tri[i-1](j];
}
for(1= 1;i <= n;1++)(
for(j=1;j<1;j++) cout << setw(6)<c tri[i](j]<e"";
cout << setw(6)<< tri(i](i] ce endl;
}
return 0;
}
九.数字方阵
数字方阵就是一个行列数相等的二维数组,其中的每个元素都是数字
解决数字方阵两种方法:
解析法
找出每一个方阵元素 f [i][j] 与 i、j 和数组规模n的通项公式,然后直接用两重循环给数组元素赋值,一般用在初始化等场合。
模拟法
把数字方阵看成一个动态的填数过程,把 n^2 个数依次填入数组中,每填好一个数,就定位好下一个数的位置 i 和 j。
例1 n阶奇数幻方
【问题描述】
行列数相等的矩阵称为方阵。把正整数 1~n 2 (n 为奇数)排成一个 n×n 方阵,使得方阵中的每一行、每一列以及两条对角线上的数之和都相等,这样的方阵称为“n 阶奇数幻方”。
编程输入 n,输出 n 阶奇数幻方。
【输入格式】
一行一个正整数 n,1≤n<20,n 为奇数。
【输出格式】
共 n 行,每行 n 个正整数,每个正整数占 5 列。
【输入样例】
5
【输出样例】
17 24 1 8 15
23 5 7 14 16
4 6 13 20 22
10 12 19 21 3
11 18 25 2 9
#include
#include
#include
using namespace std;
int dx[4]={0,1,0,-1);
int dy[4]=(1,0,-1,0};
int main(){
int n,i,j,k,ni,nj,a[21][21];
memset(a,0,sizeof(a));
cin >>n;
i=1;j=n/2+1;
a[1][j]=1;
for (k=2;k<=n
n;k++)(
if(k%n 1)i++;
else{
i–;j++;
if(i
0)i=n;
if(j== n+1)j=1;
}
a[i][j]=k;
}
for(i=1;i<=n;i++){
for(j=1;j<=n;j++)
cout << setw(5)<< a[i][j];
cout << endl;
}
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();…
输出方法
用 cout 输出整个数组:cout >> letter;
用 cout 逐个元素输出:cout >> letter[0];…
用 printf 输出整个数组:printf ("%s",letter);
用 printf 逐个元素输出:printf ("%c",letter[0]);…
用 puts 输出整个数组:puts(letter);
用 putchar 逐个元素输出:putchar(letter[0]);…
#include
using namespace std;
int main(){
char s1[20],s2[20];
scanf( “ %s ” ,s1);
scanf( “ %s ” ,s2);
printf( “ %s\n ” ,s1);
printf( “ %s\n ” ,s2);
return 0;
}
运行程序,输入“Hello world!”。
输出为:
Hello
world!
用gets
gets(s1);
gets(s2);
puts(s1);
puts(s2);
则输出为:
Hello world!
重难点:
1.数组的下标一定是从0开始
2.不能一次引用整个数组,只能逐个引用数组的单个元素
3.插入操作要把数组下标定义足够大
4.局部统计在循环体内赋初值
5.在定义二维数组时可以省略第一维的大小,但是第二维的大小不能省略
6.二维数组的输入输出操作是针对每一个元素进行,结合两个维度的下标变化,用循环嵌套实现
7.需要注意的是,在用scan的%s格式或gets读人字符串时,会在字符串末尾自动添加空字符’\0’。而使用getchar等方法读入字符串时,则要在字符串后手工加\0’。
8.gets函数用来输入一行字符串,仅以回车符结束输入,没有限制读取的字符串长度,如果输入的字符串太长会导致溢出;scanf函数用来读取一个字符串时,字符串中不能出现空格,因为scand是格符、回车符、Tab符结束一次输人
学习感受
数组用于存储单一数据类型的一组数,数组是有类型属性的,同一数组中的每一个元
素都必须属于同一数据类型。一个数组在内存中占一片连续的存储单元。感觉本章的题 目比较难,尤其要弄清楚循环体的结构,再一个下标一定要大于元素个数,输入输出要选择合适的方法,否则会出现输出结果与题目要求不一致,运算超时的问题,这一章算是结合了前面学过的全部知识,要求也是比较高。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值