第五单元 数组内容总结

第五单元 数组内容总结
一.单元知识点及难点
第一课 一维数组的定义
数组就是一组相同类型的变量,它们往往都是为了一批对象的统一属性,如一个班级所有同学的身高、全球所有国家的人口数等数组可以是二维或多维的。在数学中可以用h(1≤i≤50)表示第个同学的身高,在C++中,使用一维数组时,一般是从0开始编号h[i]就表示第i+1个同学的身高。读入50个同学的身高,语句就可以这样书写for(i=0;i<=49:i++)cin使用了数组和循环后,即使读入10000名同学的身高,代码也不长了,只要修改成9999”即可。所以,数组经常应用在大批量、同一类型的数据处理任务中。
定义一维数组的格式如下:
类型标识符 数组名 [常量表达式]
其中,类型标识符可以是任何基本数据类型,也可以是结构体等构造类型,相同类型的数组可以一起定义。数组名必须是合法的标识符。常量表达式的值即为数组元素的个数例如,“int h [50]就表示定义一个一维数组上,共有50个元素,它们的编号0开到49,每个元素都是in类型。
数组定义好后就可以“引用”数组中的任一个元素、引用格式为“数组名[下标]h[5].h[i*2+1]其中,下标只为整型常量或整型表达式,值必须在数组定义的下标范围内是否会出现"下标越界错"需要注意的是,不能一次引用整个数组,只能个引用数组的单个元素。例如,对于一个数组a来说,语句"cout<a"是不合法的。
数组的储存结构:例如,对于已经定义的数组" int h [50]“假如系统给他分配的内存单元地址从1000开始则称1000为该数组在内存中的"首地址”
整个数组所占的内存大小等于数组元素类型的大小乘以数组元素的个数。C++还提供了一个sizeof函数可以直接求出一个数组所的内存空间。同时,根据数组在内存单元中的首地址和数组类型,可以计算出该数组中任意第i个元素的起始地址。

第二课 一维数组的输入输出
由于对数组的操作只能逐个引用单个元素。所以,一维数组的输入、输出等操作,都是采用循环语句结合下标变化逐个元素进行。一般通过键盘读入和直接赋值进行批量输入。
C++提供两个函数给数组进行整体赋值(1)memset函数是给数组按字节进行赋值一般用在char语句,如果int类型的数组一般赋值0和-1。使用前需要头文件#include。
(2) fill函数是给数组按元素进行赋值可以是整个属于也可以是部分连续元素。使用前需要包含头文件#include[algorithm]
而且 在定义数组时还支持给所有活着部分元素赋值:int a[10]=(0,1.2,3,4,5,6,7,8,9);
int a[10]=(01,2,3,4)😕/部分赋初值,后面的元素自动初始化为0
int a[]=(1,2,3,4,5)//不定义数组长度,直接根据赋值个数定
1.以走楼梯为例:
【问题分析】
假设f(i)表示走到第i级楼梯的走法,则走到第i(i>2)级楼梯有两种可能:一种是从第i-1级楼梯走过来;另一种是从第i-2级楼梯走过来。根据加法原理,f(i)=f(i-1)+(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]);
	printf("%d\n",f[n]);
	return 0;
}

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

#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 flaq=flase;
	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;
}

第三课 一维数组的插入与删除
插入操作时要注意把数组的下标定义的足够大
1.以插队问题为例:
【问题分析】
N个人的排队情况可以用数组q表示,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]);
	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\n",q[n]);
	return 0;
}

2.以队伍调整为例:

#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=x;i<n;i++)
	q[i]=q[i+1];
	n--;
	for (i=1;i<n;i++)
	pritnf("%d",q[i]);
	printf("%d\n",q[n]);
	return 0;
}

第四课 一维数组的查找统计
一维数组的查找操作,就是在一维数组中查找有没有某个元素,它的值等于指定的值x查找操作的结果可能是一个没找到、找到一个或者找到很多个。常见的查找算法有“序”查分”查找序查就是按照从前往后的顺序,将数组中的元素依次与要找的数x进行比校。如果数中的元素有序的(递增或者递减),也可以采用二分查找分查称折查找,其优点是比较次数少、查找速度快。假设数组an是严格递增的,每个元素都是现在要查找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 printf("not find\n");

2.以比身高为例
全据统计定义可在定义变量时赋初值,而局部统计一定在具体统计前赋初值。

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

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

#include<cstdio>
using namespace std;
int main()
{
	int n,j,i,k,temp,h[101];
	cin>>n;
	for (i=1;i<=n;i++)
	cin>>h[i];
	for (i=1;i<=n;i++)
	{
		k=i;
		for (j=1+i;j<=n;j++)
			if(h[j]<h[k])
			k=i;//在i~n之间最小元素
		temp=h[i];
		h[i]=h[k];
		h[k]=temp;//将i~n之间的最小元素放到第i个位置
	}
	for (i=1;i<n;i++)
	cout<<h[i]<<" ";
	cout<<h[n]<<endl;
	return 0;
}

2.以站队之冒泡排序为例:

#include<cstdio>
using namespace std;
int main()
{
	int n,i,j,temp,h[101];
	cin>>n;
	for (i=1;i<=n;i++)
	cin>>h[i];
	for (i=1;i<n;i++)
	{
		bool flag = true;
		for (j = 1;j<=n;j++)
			if(h[j]>h[j+1])
			{
				temp=h[j];
				h[j]=h[j+1];
				h[j+1]=temp;
				flag = flase;
			}
		if(flag) break;
	}
	for (i=1;i<n;i++)
	cout<<h[i]<<" ";
	cout<<h[n]<<endl;
	return 0;
}

3.以站队之插入顺序为例:

#incldue<cstdio>
using namespace std;
int main()
{
	int n,i,j,k,temp,h[101];
	cin>>n;
	for (i=1;i<=n;i++)
	cin>>h[i];
	for (i=2;i<=n;i++)
	{
		temp=h[i];
		k=1;
		while (h[k]<=temp&&k<i)
		k++;
		for (j=i-1;j>=k;j--)
		h[j+1]=h[j];
		h[k]=temp;
	}
	for (i=1;i<n;i++)
	cout << h[i] <<" ";
	cout << h[n] << endl;
	return 0;
}

第六课 一维数组的应用举例
1.以商品排序为例:
【问题分析】
本题可以选用学过的任意一种排序算法实现,但是测试程序发现会“超时”,因为本题最多有100000件商品,三种排序都需要两层循环嵌套。
其实,分析数据发现一个重要特征:数据虽然很多,但是数据范围比较小。这种情况下,可以使用另外一种排序算法——桶排序,定义一个int型数组 num[1001],num[x]记录整数x出现的次数,初始化都为0,没读到一个数x,就执行num[x]=num[x]+1。输出时,从0~1000穷举x,每个x输出num[x]次。

#include<cstdio>
using namespace std;
int n,j,i,number,num[1001];
int main()
{
	cin>>n;
	for (i=1;i<=n;i++)
		{
			cin>> number;
			num[number]++;//记录整数number出现的次数
		}
		for (i=0;i<1001;i++)
}

2.素数大酬宾之筛选法

#include<cstdio>
#include<cmath>
using namespace std;
int main()
{
	int n,j,i;
	bool p[100001];
	for (i=0;i<=100000;i++)
	p[i] = true;
	p[1] = flase;
	cin>>n;
	cout<<2;
	for (i=2;i<=sqrt(n);i++)
		if(p[i])
			for (j=2;i*j<=n;j++)
			p[i*j]=flase;
	for (i=3;i<=n;i++)
		if(p[i])
		cout << " " << i;
		cout << endl;
	return 0;
}

第七课 二维数组的定义和操作
一维数组的每一个元素又是一个一维数组,称这种数组为“维数组。定义二维数组的一般格式为:类型标识符 数组名[常量表达式1] [常量表达式2];常量表达式的乘积就是二维数组的个数。二维数组的输入输出:
1.回形方阵之对称法

#include<iostream>
using namespace std;
int n,j,i,k,a[10][10];
int main()
{
	cin>>n;
	for (k=1;k<=(n+1)/2;k++)
		for(i=k;i<=n+1-k;i++)
			for(j=k;j<=n+1-k;j++)
				a[i][j]=k;
	for (i=1;i<=n;i++)
	{
		for(j=1;j<n;j++)
			cout << a[i][j] <<" ";
			cout << a[i][n] << endl;
	}
	return 0;
}

第八课 二维数组的应用举例
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<iomanip>
using namespace std;
int n,j,i,tri[21][21];
int main()
{
	cin>>n;
	for(i=1;i<=n;i++)
	{
		tri[i][1]=1;
		tri[i][i]=1;
		for(j=2;j<i;j++)
		tri[i][j] = tri[i+1][j-1] + tri[i-1][j];
	}
	for(i=1;i<=n;i++)
	{
		for(j=1;j<i;j++)
		cout << setw(6) << tri[i][j] << " ";
		cout << setw(6) << tri[i][i] <<endl;
	}
	return 0;
}

第九课 数字方阵
数字方阵就是一个行列数相等的二维数组,其中的每个元素都是数字。解决数字方阵问题一般有两种方法:解析法和模拟法。解析法就是找出每一个方阵元素与和数组规模n的通项公式,然后直接用两重循环给数组元素赋值,相对比较容易,一般用在初始化等场合模拟法就是把数字方阵看成一个动态的填数过程,把n个数依次填入数组中,每填好一个数,就定位好下一个数的位置i和j。
1.以n阶奇数幻方为例:
[问题分析]
定义一个二数组模拟填数的过程。分析样例发现,n阶奇数幻方可以按下列方法生成先把数字1填在第1行的正中间a1n/2+1]然用一个循环穷举k,填入数字2-n2,每次先找位置再填数,找位置的规律如下:如果数k填在第行第列,那么一般情况下,下一个数k+1应该填在它的右上方,即第i-1行第j+1列。但是,有两种特殊情况:如果右上方无格子,也就是越界了(i-1=0或j+1=n+1),那么就应该把下一个数放到第n行或者第1列如果右上方已经有数了,那么下一个数k+1就应该填在第k个数的正下方。

#include<iostream>
#include<iomanip>
#include<cstring>
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[i][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(i=1;j<=n;j++)
			cout << setw(5) << a[i][j];
		cout << endl;
	}
	return 0;
}

第十课 字符数组
如果数组中的每个元素都是一个字符,这样的数组称为字符数组有时,把一维字符数又称为“字符串”定义字符数组的方法与定义其他类型数组的方法类似。
给字符数赋值的方法很多,例如:
用字符常量逐个初始化:char letter[3]=[‘a’,‘e’,‘o’]
用赋值语句逐个元素值letter[o]=‘a’
1.以数字和为例:
【问题分析】
由于n可能到200位,任何整数类型都是不可能存储的。因此定义一个一维字符数组读取存储这个超大数,然后把每个字符转换成数值累加求和。

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
char n[201];
int main()
{
	int n,sum=0;
	scanf("%s",&n);
	for (i=0;i<strlen(n);i++)
	sum=sum+n[i]-'0';//strlen(n)表示求字符串的长度
	printf("%d\n",sum);
	return 0;
}

二章节易错点整

  1. 类型标识符可以是任何基本数据类型,也可以是结构体等构造类型,相同类型的数组可以一起定义。数组名必须是合法的标识符。
  2. 下标只为整型常量或整型表达式,值必须在数组定义的下标范围内是否会出现"下标越界错"需要注意的是,不能一次引用整个数组,只能个引用数组的单个元素。例如,对于一个数组a来说,语句"cout<a"是不合法的。
  3. 空格作为间隔符不作文字内容。
  4. scanf语句空格之前系统自动认为前一段文字;
  5. 空格之后系统自动认为下一段文字。
  6. 数组大小必须是值为正的常量不能是变量。
  7. 数组定义后的初值仍然是随机数一般需要初始化。
  8. C++sort函数的用法
  9. #include
    u sing namespace std;
    默认的soet函数是按升序排;
    sort(a,a+n);//两个参数分别是待排序数组的首地址和尾地址

三学习中遇到的困难及如何解决
1.因为定义下标太小导致错误,知道了以后要定心下标稍微大一点,防止下标越界。
2.作用特别函数时一定要记得头文件。
3.批量输入时记得循环嵌套
4。各种排序方法要真正理解再去运用。

四 本章学习心得
在本章的学习中,理解了数组的定义包括一维与二维,掌握了一维数组元素引用和物理存储的方式。熟悉掌握了一维数组的输入与输出,插入和删除,学会了通过一维数组输入与输出,插入与删除解决一些实际问题。掌握了选择排序,冒泡排序和插入排序,懂得了应用算法解决实际问题。学会了跟踪数组元素的调,综合应用一维数组的基本操作解决一些实际问题。理解了二维数组的存储结构掌握了其初始化,;输入输出等基本操作,并解决一些实际问题。并且用二维数组解决一些方阵的问题。掌握了字符数组输入输出方法,应用字符数组解决一些实际问题。整个第五单元围绕数组这个概念展开了这种定义及算法,是的程序编程更为优化,我自己的程序能力也有所加强,数组的确带来了很多方便。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值