C++第五单元 数组

本教程深入讲解C++中的一维数组,包括定义格式、输入输出、插入删除、查找统计、排序算法及应用实例。通过斐波那契数列、站队问题、商品排序等例子,阐述数组在编程中的重要性与使用技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

第1课 一维数组的定义

数组: 为了表示同一批对象的统一属性。

定义格式: 类型标识符 数组名[常量表达式];

(类型标识符可以为任何基本数据类型或结构体;数组名必须是合法的标识符;常量表达式的值为数组元素个数。)

int d[50],g[100];
int a[5*10];
#define N 50
int b[N];

引用数组的格式: 数组名[下标]

(下标只能为整型常量或整型表达式,值必须在数组定义的下标范围内,不能一次引用整个数组,只能逐个引用数组的单个元素。)


第2课 一维数组的输入与输出

利用循环语句逐个输出数组元素,例:

int h[100];
for(i=0;i<100;i++) cout<<h[i];

数组赋值:

​键盘读入

int h[100];
fot(i=0;i<100;i++) cin>>h[i];
  • ​直接赋值
    int h[100],a[20];
    for(i=0;i<100;i++) h[i]=0;
    for(i=0;i<20;i++) a[i]=i*2+1;

     

  • ​“整体”赋值

 ①memset函数:“按字节”赋值,一般用于char型数组,若是int类型的数组,一般赋值为0或1。使用前包含头文件#include<cstring>。

②fill函数:“按元素”赋值,可以是整个数组或部分连续元素,可以赋任何值。需包含头文件#include<algorithm>。

可在定义数组的同时,给所有或部分元素赋值,例:

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};//不定义数组长度,直接根据赋值个数定

经典例题:走楼梯

【问题分析】

假设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;
}

第3课 一维数组的插入删除

插入操作时应注意将数组定义的足够大。

例:插队问题

【问题分析】

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

第4课 一维数组的查找统计

常见查找算法:“顺序”查找和“二分”查找。

顺序查找:按从前到后的顺序,将数组中的元素依次与要查找的数x进行比较。

二分查找:又叫“折半”查找,其优点是比较次数少,查找速度快。

假设数组a[n]是严格递增的,每个元素都是int型,现在要查找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");

经典例题 比身高:

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

全局统计可以在定义变量时赋初值,局部统计在统计开始之前赋值。


第5课 一维数组的元素排序

最基本的三种排序算法:选择排序、冒泡排序和插入排序。

经典例题 站队:

选择排序

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

冒泡排序

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

插入排序

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

第6课 一维数组的应用举例

经典例题 商品排序:

【问题分析】

分析数据发现一个重要特征:数据虽然很多,但是数据范围比较小。这种情况下,可以使用另外一种排序算法——桶排序,定义一个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++)
}

素数大酬宾(筛选法):

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

第7课 二维数组的定义和操作

格式:类型标识符 数组名[常量表达式1][常量表达式2];

(常量表达式1的值表示第一维大小,常量表达式2的值表示第二维大小,二者乘积就是二维数组的元素个数。) 

例 回型方阵:

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

第8课 二维数组应用举例

杨辉三角形:

【问题分析】

定义一个二维数组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;
}

第9课 数字方针

例 蛇形方阵:

【问题分析】

可以把蛇形方阵看成一条一条的直线(从右上到左下的斜线),每条直线上的数的个数为:1,2,3,...,n-1,n,n-1,...,3,2,1。每条直线上的元素位置有一一个重要特点:行号和列号相加为定值,从2到2xno同时,还可以分析出对称性.以最中间的直线为界,左上角和右下角的两个区域里的所有数的位置都是对称的,满足a[i][j]+a[n+1-i][n+1-j]等于nxn+1。因此,只需要模拟填出前n条直线上的数字,另外n-1条的元素值直接通过对称性来赋值。

#include<iostream>
#include<iomanip>
#include<cstring>
using namespace std;
int main(){
	int n,i,j,k,t=0,a[21][21];
	cin>>n;
	for(k=1;k<=n;k++)
	    if(k%2)
		   for(j=1;j<=k;j++){
			   i=k+1-j;
			   t++;a[i][j]=t;
			   a[n+1-i][n+1-j]=n*n+1-t;}
	    else
		   for(j=k;j>=1;j--){
			   i=k+1-j;
			   t++;
			   a[i][j]=t;
			   a[n+1-i][n+1-j]=n*n+1-t;}
	for(i=1;i<=n;i++){
		for(j=1;j<=n;j++);
		    cout<<setw(5)<<a[i][j];
		cout<<endl;}
	return 0;
	}

第10课 字符数组

如果数组中的每个元素都是一个字符,这样的数组称为字符数组有时,把一维字符数又称为“字符串”定义字符数组的方法与定义其他类型数组的方法类似。

给字符数赋值的方法很多,例如:

用字符常量逐个初始化:char letter[3]=[‘a’,‘e’,‘o’]

用赋值语句逐个元素值letter[o]=‘a’

例 数字和:

【问题分析】

由于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;
}

心得:

理解了数组的含义,学会了一维数组的定义并掌握了一维数组的元素引用、物理存储方式、输入输出操作、元素插入和删除操作和在一维数组中进行元素查找,也可以用一维数组解决一些实际问题,学会了三种排序算法和跟踪数组元素调试程序。也学习了有关二维数组的基本操作,并综合应用二维数组的基本操作解决一些实际问题,通过数字方阵体会了数组的下标运算,掌握了字符数组的输入输出方法。本单元整体围绕数组进行详细的讲解,这种定义方法也简化了编程的整体结构,提高了编程效率,数组为我们的编程带来了便利,应好好利用。

定义下标时应注意下标的大小;注意引用数组元素时下标不能越界,下标编号都是从0开始的;引用整个数组时应通过循环语句进行逐一赋值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值