Bootstrap

C++蓝桥杯基础篇(五)

片头

嗨~小伙伴们,大家好!今天,我们来一起学习C++蓝桥杯基础篇(五),准备好了吗?咱们开始咯~


一、一维数组

1.1 数组的定义

数组的定义方式和变量类似。

#include<iostream>
#include<algorithm>
using namespace std;

int main() {
	int a[10], b[20];
	float f[33];
	double d[123];
	char c[21];
	string g[25];


	return 0;
}
1.2 数组的初始化

在main函数内部,未初始化的数组中的元素是随机的。

int main() {
	int a[3] = { 0,1,2 };		//含有3个元素的数组,元素分别为0,1,2
	int b[] = { 0,1,1 };		//长度为3的数组
	int c[5] = { 1,2,3 };		//等价于c[] = {1,2,3,0,0}
								//定义了一个长度为5的数组,没有给出的值,默认是0
	char d[3] = { 'a','b','c' };//字符数组的初始化

	int f[10] = { 0 };			//将数组全部初始化为0的写法
	return 0;
}
1.3 访问数组元素

通过下标访问数组

int main() {
	int a[10] = { 0 }; //定义1个长度为10的a数组
	for (int i = 0; i < 10; i++) {  //输入元素
		cin >> a[i];
	}

	for (int i = 0; i < 10; i++) {  //输出元素
		cout << a[i] << " ";
	}
	cout << endl;
	return 0;
}

再来一个例子:

int main() {
	int aa[100] = { 0 };      //定义长度为100的aa数组,初始化全为0 
	aa[0] = 1;                //数组下标一定从0开始
	int c = aa[0] * 2;

	cout << aa[0] << endl;    //aa[0]仍然为1

	int a[3] = { 1,2,3 };
	cout << a[0] << " " << a[1] << " " << a[2] << endl;
	a[0] = 5;
	cout << a[0] << endl;     //a[0]的值被修改为5

	return 0;
}

练习1:使用数组实现求斐波那契数列的第n项

斐波那契数列:f(1)=0,f(1)=1,f(2)=1,f(3)=2,f(4)=3,f(5)=5,f(6)=8,...,f(n)=f(n-1)+f(n-2)

代码如下:

//练习题1: 使用数组实现求斐波那契数列的第n项
int main() {
	int f[1000];    //定义长度为1000的数组
	f[0] = 0;       //第一个元素值为0
	f[1] = 1;       //第二个元素值为1

	int n;
	cin >> n;
	for (int i = 2; i <= n ; i++){
		f[i] = f[i - 1] + f[i - 2]; //所求的数 = 前2个数之和
	}
	cout << f[n] << endl;

	return 0;
}

中间的循环部分,写成这样亦可:

	for (int i = 1; i <= n; i++) {   //下标i从1开始,到n结束
		f[i + 1] = f[i - 1] + f[i];  
	}

练习2:输入1个n,再输入n个整数,将这n个整数逆序输出

代码如下:

//练习题2: 输入1个n,再输入n个整数,将这n个整数逆序输出
int main() {
	int n;
	cin >> n;

	int a[100];
	for (int i = 0; i < n; i++) {
		cin >> a[i];
	}

	for (int j = n - 1; j >= 0; j--) {
		cout << a[j] << " ";
	}
	cout << endl;

	return 0;
}

练习3:输入一个n,再输入n个整数,将这个数组顺时针旋转k(k<=n)次,最后将结果输出

比如:数组里面有7个元素,分别为 1,  2,  3,  4,  5,  6,  7,现在我们将数组中的元素向右旋转3个位置

第一次旋转:将最后一个元素"7" 放在第一个位置,后面的元素依次往后移动,变成 7,  1,  2,  3,  4,  5,  6

第二次旋转:将最后一个元素"6" 放在第一个位置,后面的元素依次往后移动,变成 6,  7,  1,  2,  3,  4,  5

第三次旋转:将最后一个元素"5" 放在第一个位置,后面的元素依次往后移动,变成 5,  6,  7,  1,  2,  3,  4

针对这道题,我们提供3种方法

方法一:将最后一个元素保存到temp临时变量,将前n-1个数(下标从0~n-2)依次往后挪动1位,最后将temp放入第1个位置。像这样循环k次,即可得到答案。

代码如下:

//解法1
void Reverse(int a[], int k, int n) {
	
	while (k--) {
		int temp = a[n - 1];			  //将最后一个元素保存到temp变量中
		for (int i = n - 2; i >= 0; i--)  //从倒数第2个元素开始,依次往后挪动1位
		{
			a[i + 1] = a[i];
		}
		a[0] = temp;					 //将temp放入数组的第1个位置
	}
}

int main() {
	int a[100];
	int n;
	cin >> n;
	for (int i = 0; i < n; i++) {
		cin >> a[i];
	}

	int k;	//旋转次数
	cin >> k;
	Reverse(a, k, n);

	for (int i = 0; i < n; i++) {
		cout << a[i] << " ";
	}

	return 0;
}

方法二:我们可以定义reverse函数,将前n-k个元素逆置,后k个元素逆置,最后将整体逆置

 我们把数组分成3个部分逆置,假设数组里面有7个元素,分别为 1,2,3,4,5,6,7,现在我们将数组中的元素向右旋转3个位置

第一个部分:前n-k个逆置,这里的n为7,k为3,也就是前4个逆置,变成 4,3,2,1,5,6,7

第二个部分:后k个逆置,这里的k为3,也就是后3个逆置,变成 4,3,2,1,7,6,5

第三个部分:整体逆置,变成了 5,6,7,1,2,3,4

代码如下:

void Reverse1(int a[], int left, int right) {
	while (left < right) {    //当left<right的时候,进入循环
		int temp = a[left];   //用临时变量temp实现逆置(左右元素互换)
		a[left] = a[right];
		a[right] = temp;
		left++;               //每交换完一次,left向右移动
		right--;              //每交换完一次,right向左移动,直到2个变量相遇
	}
}

//解法2
int main() {
	int a[100];
	int n;
	cin >> n;
	for (int i = 0; i < n; i++) {
		cin >> a[i];
	}

	int k;
	cin >> k;
	Reverse1(a, 0, n - k - 1);	//前n-k个数逆置
	Reverse1(a, n - k, n - 1);	//后k个数逆置
	Reverse1(a, 0, n - 1);		//整体逆置

	for (int i = 0; i < n; i++) {
		cout << a[i] << " ";
	}

	return 0;
}

 嗯,这个方法好是好,但是如果我第一次做这种题,肯定想不出来,有木有第三种思路呢?

有!下面介绍第三种方法

方法三:定义一个新的数组temp,使用memcpy函数将原数组的内容拷贝到新数组中去,拷贝元素的同时,也就完成了逆置。

代码如下:

//解法3
void Reverse2(int a[], int n, int k) {
	int temp[20] = { 0 };						//定义一个临时数组temp,初始化数组为0
	memcpy(temp, a + n - k, sizeof(int) * k);	//将原数组的后k个数拷贝到temp数组前面位置
	memcpy(temp + k, a, sizeof(int) * (n - k)); //将原数组的前n-k个数拷贝到temp数组后面位置
	memcpy(a, temp, sizeof(int) * n);			//将temp数组中的元素拷贝回原数组
}


int main() {
	int a[100];
	int n;		//n个元素
	cin >> n;	
	for (int i = 0; i < n; i++) {
		cin >> a[i];
	}

	int k;		//旋转k次
	cin >> k;

	Reverse2(a, n, k);

	for (int i = 0; i < n; i++) {
		cout << a[i] << " ";
	}

	return 0;
}

练习4:输入n个数,将这n个数从小到大的顺序输出

我们可以采用任意一种排序方法来解决此题,我用的是选择排序

代码如下:

//输入n个数,将这n个数从小到大的顺序输出
void swap(int& a, int& b) {
	int temp = a;
	a = b;
	b = temp;
}

int main() {
	int arr[1000];
	int n;
	cin >> n;
	cout << endl;

	int i, j;
	for (i = 0; i < n; i++) {
		cin >> arr[i];
	}

	//选择排序
	for (i = 0; i < n - 1; i++) {
		for (j = i + 1; j < n; j++) {
			if (arr[i] > arr[j]) {
				swap(arr[i], arr[j]); 
			}
		}
	}

	for (i = 0; i < n; i++) cout << arr[i] << " ";
	cout << endl;

	return 0;
}

 练习5:计算2的N次方。N<=10000

注意啦:这里的N比较大,我们可以举一个例子:

我们可以运用小学数学知识,求出个位、十位、百位、千位、万位....

因此,本道题代码如下:

//计算2的N次方。N<=10000

const int N = 3010;

int main9() {
	int arr[N] = { 1 };  //arr数组中有N个元素,除了第一个元素为1,其余全为0
	int n;
	cin >> n;
	int m = 1; //表示后一个位置的下标

	for (int i = 0; i < n; i++) {
		int t = 0;	//表示进位
		for (int j = 0; j < m; j++) {
			t += arr[j] * 2;
			arr[j] = t % 10;  
			t /= 10;
		}
		if (t) arr[m++] = t;
	}

	for (int k = m - 1; k >= 0; k--){
		printf("%d", arr[k]);
	}
	cout << endl;

	return 0;
}

二、多维数组

多维数组就是数组的数组

比如:

 int a[6][5]  //数组a是一个二维数组,6行5列

 a[0]: {a[0][0],a[0][1],a[0][2],a[0][3],a[0][4]}

 a[1]: {a[1][0],a[1][1],a[1][2],a[1][3],a[1][4]}

 a[2]: {a[2][0],a[2][1],a[2][2],a[2][3],a[1][4]}

 a[3]: {a[3][0],a[3][1],a[3][2],a[3][3],a[3][4]}

 a[4]: {a[4][0],a[4][1],a[4][2],a[4][3],a[4][4]}

 a[5]: {a[5][0],a[5][1],a[5][2],a[5][3],a[5][4]}

我们可以举一个例子:

int main() {
	int a[3][4];

	int i, j;
	for (i = 0; i < 3; i++) {
		for (j = 0; j < 4; j++) {
			a[i][j] = i + j;
		}
	}

	for (i = 0; i < 3; i++) {
		for (j = 0; j < 4; j++) {
			cout << a[i][j] << " ";
		}
		cout << endl;
	}

	return 0;
}

运行结果为:


话不多说,我们开始做题咯~

习题6:数组替换

代码如下:

//数组替换
//输入一个长度为10的整型数组x[10],将里面的非正整数全部替换为1
//输出替换完成后的数组
//输入包含10个整数,每个整数占1行
//输出新数组中的所有元素,每个元素占1行
//输出格式为"x[i] = x",其中i为元素编号(从0开始),x为元素的值

int main() {
	int a[10];

	int i;
	for (i = 0; i < 10; i++) {
		cin >> a[i];
	}

	for (i = 0; i < 10; i++) {
		if (a[i] <= 0)
			a[i] = 1;
	}

	for (i = 0; i < 10; i++)
		printf("x[%d] = %d\n", i, a[i]);

	cout << endl;

	return 0;
}

习题7:数组填充

代码如下:

//数组填充
//输入一个整数v,输出一个长度为10的数组n
//数组中的第一个元素为v,每个后续元素的值都为上一个元素值的2倍
//例如:如果输入整数为1,则数组为:1,2,4,8
//输入一个整数v
//输出数组中的所有元素,每个元素占一行
//输出格式为"n[i]=x",其中,i为元素编号(从0开始),x为元素的值

int main() {
	int arr[10];
	int v;
	cin >> v;

	arr[0] = v;    //数组中的第一个元素为v
	for (int i = 1; i < 10; i++) {
		arr[i] = arr[i - 1] * 2;   //每个后续元素的值都为上一个元素值的2倍
	}

	for (int j = 0; j < 10; j++) {
		printf("N[%d] = %d\n", j, arr[j]);
	}

	return 0;
}

习题8:数组选择

代码如下:

//数组选择
//输入一个长度为100的数组A,请按顺序输出其中不大于10的所有元素
//输入100个元素,每个数占一行,表示数组的所有元素的值
//每个数可能是整数也可能是浮点数
//按顺序输出数组中的所有不大于10的元素,每个元素占1行
//输出格式为"A[i] = x",其中i为元素编号,x为元素的值
//注意,所有的x均保留1位小数

int main() {
	double a[100];
	for (int i = 0; i < 100; i++) {
		cin >> a[i];
	}

	for (int j = 0; j < 100; j++) {
		if (a[j] <= 10) {
			printf("A[%d] = %.1lf\n", j, a[j]);
		}
	}

	return 0;
}

习题9:数组中的行

题目要求二维数组中某一行的元素的平均值或元素的和,说明行是固定的,列的取值范围 0~11 

代码如下:

//数组中的行
//输入一个二维数组m[12][12]
//根据输入的要求,求出二维数组中某一行的元素的平均值或元素的和
//第一行输入整数L,表示所求的具体行数(行数从0开始计数)
//第二行包含一个大写字母,若为's',则表示需要求出第L行的元素的和
//若为'm',则表示需要求出第L行的元素的平均值
//接下来的12行,每行包含用空格隔开的浮点数,表示这个二维数组
//其中,第i+1行的第j+1个数表示数组元素m[i][j]
//输出一个数,表示所求的平均数或元素的和的值,保留1位小数

int main() {
	int m[12][12];
	int L;//表示所求的具体行数
	cin >> L;

	char t;
	cin >> t;

	//输入一个二维数组m[12][12]
	for (int i = 0; i < 12; i++) {
		for (int j = 0; j < 12; j++) {
			cin >> m[i][j];
		}
	}

	double sum = 0;
	//求出二维数组中某一行的元素的平均值或元素的和
		for (int j = 0; j < 12; j++) {
			sum += m[L][j];
		}

		if (t == 's') printf("sum = %.1lf\n", sum);
		else printf("average = %.1lf\n", sum / 12);

	return 0;
}

习题10:数组的右上半部分

这道题,实质上是找规律,找行数和列数的关系

行数 i列数 j
01~11
12~11
23~11
45~11
56~11
67~11
78~11
89~11
910~11
1011
ij+1~11

通过上表,观察规律,我们可以得知,列数的起始位置 = 行数+1,本道题代码如下:

//数组的右上半部分
//输入一个二维数组m[12][12]
//求二维数组的右上部分元素的平均值或元素的和
//右上部分指对角线上方的部分
//第一行输入一个大写字母,若为's',则表示需要求出右上半部分的元素的和
//若为'm',则表示需求出右上半部分的元素的平均值
//接下来12行,每行包含12个用空格隔开的浮点数,表示这个二维数组
//其中第i+1行的第j+1个数表示数组元素m[i][j]
//输出1个数,表示所求的平均数或和的值,保留1位小数

int main() {
	char t;
	cin >> t;
	double m[12][12];

	for (int i = 0; i < 12; i++) {
		for (int j = 0; j < 12; j++) {
			cin >> m[i][j];
		}
	}

	double sum = 0;
	int num = 0;
	for (int i = 0; i < 11; i++) {
		for (int j = i + 1; j < 12; j++) {
			sum += m[i][j];
			num++;
		}
	}

	if (t == 's') printf("sum = %.1lf\n", sum);
	else printf("average = %.1lf\n", sum / num);

	return 0;
}

习题11:数组的左上半部分

这道题,仍然是寻找行数和列数的规律

行数 i列数 j
00~10
10~9
20~8
30~7
40~6
50~5
60~4
70~3
80~2
90~1
100
i0~10-i

通过上表,观察规律,我们可以得知,列数的终止位置 = 10-行数,本道题代码如下:

//数组的左上半部分
//输入一个二维数组m[12][12]
//求二维数组的右上部分元素的平均值或元素的和
//右上部分指对角线上方的部分
//第一行输入一个大写字母,若为's',则表示需要求出右上半部分的元素的和
//若为'm',则表示需求出右上半部分的元素的平均值
//接下来12行,每行包含12个用空格隔开的浮点数,表示这个二维数组
//其中第i+1行的第j+1个数表示数组元素m[i][j]
//输出1个数,表示所求的平均数或和的值,保留1位小数

int main() {
	char t;
	cin >> t;
	double m[12][12];

	for (int i = 0; i < 12; i++) {
		for (int j = 0; j < 12; j++) {
			cin >> m[i][j];
		}
	}

	double sum = 0;
	int num = 0;
	for (int i = 0; i < 11; i++) {
		for (int j = 0; j <= 10 - i; j++) {
			sum += m[i][j];
			num++;
		}
	}

	if (t == 's') printf("sum = %.1lf\n", sum);
	else printf("average = %.1lf\n", sum / num);

	return 0;
}

习题12:数组的上方区域

 这道题,仍然是寻找行数和列数的规律

行数 i列数 j
01~10
12~9
23~8
34~7
45~6
ii+1 ~ 10-i

通过上表,观察规律,我们可以得知,列数的起始位置 = 行数+1列数的终止位置 = 10-行数,本道题代码如下:

//数组的上方区域
//输入一个二维数组m[12][12],根据输入的要求
//求出二维数组的上方区域元素的平均值或元素的和
//数组的2条对角线将数组分为了上下左右四个部分
//黄色部分为对角线,绿色部分为上方区域
//第一行输入一个字母,若为's',则表示需要求出上方区域元素的和
//若为'm',则表示需求出上方区域的元素的平均值
//接下来12行,每行包含12个用空格隔开的浮点数,表示这个二维数组
//其中第i+1行的第j+1个数表示数组元素m[i][j]
//输出1个数,表示所求的平均数或和的值,保留1位小数

int main() {
	char t;
	cin >> t;
	double m[12][12];

	for (int i = 0; i < 12; i++) {
		for (int j = 0; j < 12; j++) {
			cin >> m[i][j];
		}
	}

	double sum = 0;
	int num = 0;
	for (int i = 0; i <= 4; i++) {
		for (int j = i + 1; j <= 10 - i; j++) {
			sum += m[i][j];
			num++;
		}
	}

	if (t == 's') printf("sum = %.1lf\n", sum);
	else printf("average = %.1lf\n", sum / num);

	return 0;
}

片尾

今天我们学习了C++基础篇(五),学习了数组相关的习题和知识,希望看完这篇文章对友友们有所帮助!!!

点赞收藏加关注!!!

谢谢大家!!!

;