C++菜鸟教程 - 从入门到精通 第四节

大家好,我又来了!!!

今天我们将要学习二维数组.请大家做好准备

按照上节课的知识,我们先来做一道关于and or not 的题

一.逻辑运算符的练习

1.and

题目描述

有句俗话叫“三天打渔,两天晒网”。如果小爱前三天打渔,后两天晒网,一直重复这个过程,那么在第 n 天,她是在打渔还是晒网呢?

输入格式

单个整数表示 n。

输出格式

  • 如果在打渔,输出 Fishing
  • 如果在晒网,输出 Lying

数据范围

1≤n≤10000

样例数据

输入

1

输出

Fishing

代码 
#include <iostream>
#include <cstdio>
using namespace std;
int d;                         //d表示天数
int main(){
	cin>>d;                    //输入天数
	if(d%5>=1 and d%5<=3) cout<<"Fishing"<<endl;      //三天打鱼两天晒网,5天是一个周期,在这个周期的1-3天,小爱在打鱼(输出Fishing),所以用取余来解决
	else cout<<"Lying"<<endl;  //否则,输出Lying
	return 0;
}

 2.or

题目描述

竞选班长的条件是:语文、数学、英语三门成绩中,至少两门大于或等于 90 分,而且体育不能低于 85 分。给定小明的语文、数学、英语及体育成绩,请问他能否竞选班长?

输入格式

第一行:单个整数 a ,表示语文成绩;
第二行:单个整数 b,表示数学成绩;
第三行:单个整数 c,表示英语成绩;
第四行:单个整数 d,表示体育成绩。

输出格式

  • 如果可以竞选班长,输出 Qualified
  • 否则,输出 Not qualified

数据范围

0≤a,b,c,d≤100

解析

重点部分在于判断是否可以竞选班长的表达式
有点长!
((c>=90 and m>=90)or (c>=90 and e>=90)or (m>=90 and e>=90)) and p>=85
其中c代表语文Chinese,m代表数学mathmaths,e代表英语English,p代表体育PE
前半部分是判断语数英中至少有2科>=90分;
后半部分是判断体育>=85分。

 代码

#include<bits/stdc++.h>         //这个一会讲
using namespace std;
int c,m,e,p;                //定义变量(英文首字母)
int main(){
	cin>>c>>m>>e>>p;
	if(((c>=90 and m>=90) or (c>=90 and e>=90) or (m>=90 and e>=90)) and p>=85){     //上文说的条件表达式
		cout<<"Qualified";              //输出合格
	}else cout<<"Not qualified";          //输出不合格
	return 0;
}

not我还没有找到好题,先一放,后面会更新

二.二维数组登场

如果一维数组是一条线,二维数组就是一个面

一维数组中再套一维数组,就变成二维数组

二维数组定义

多维数组最简单的形式是二维数组。一个二维数组,在本质上,是一个一维数组的列表。声明一个 x 行 y 列的二维整型数组,形式如下:

type arrayName [ x ][ y ];

其中,type 可以是任意有效的 C++ 数据类型,arrayName 是一个有效的 C++ 标识符。

一个二维数组可以被认为是一个带有 x 行和 y 列的表格。下面是一个二维数组,包含 3 行和 4 列:

C++ 中的二维数组

因此,数组中的每个元素是使用形式为 a[ i , j ] 的元素名称来标识的,其中 a 是数组名称,i 和 j 是唯一标识 a 中每个元素的下标。

二维数组初始化

多维数组可以通过在括号内为每行指定值来进行初始化。下面是一个带有 3 行 4 列的数组。

int a[3][4] = {  
 {0, 1, 2, 3} ,   /*  初始化索引号为 0 的行 */
 {4, 5, 6, 7} ,   /*  初始化索引号为 1 的行 */
 {8, 9, 10, 11}   /*  初始化索引号为 2 的行 */
};

也可以分开初始化

int array2[2][3];

array2[0][0] = 1;

array2[0][1] = 2;

array2[0][2] = 3;

array2[1][0] = 4;

array2[1][1] = 5;

array2[1][2] = 6;

动态分配内存,一笔带过

int** array3 = new int*[2];
for(int i = 0; i < 2; i++)
    array3[i] = new int[3];

 注意,动态分配的二维数组只能使用指针来进行

二维数组引用 

二维数组中的元素是通过使用下标(即数组的行索引和列索引)来访问的。例如:

int val = a[2][3];

上面的语句将获取数组中第 3 行第 4 个元素。

二维数组练习 

题目描述

在一个n行m列的二维数组中,有若干奇数和偶数,请编程统计出这个二维数组中,奇数和偶数分别有多少个?

输入

第一行是两个整数n和m(n和m都是4~100之间的整数),代表接下来的二维数组有n行m列。
接下来n行,每行有m个整数。(这些整数都是0~9999之间的整数)

输出

两个整数用空格隔开,分别代表二维数组中奇数、偶数的个数

样例输入 

2 2
2 3
4 6

样例输出 

1 3
代码 
#include <iostream>		
#include <cstdio>								
using namespace std;
int n,m,s,o,b[101][101];    //比100多1,预留空间
int main(){	
	cin>>n>>m;
	for(int i=0;i<n;i++){   //遍历列
		for(int j=0;j<m;j++){   //遍历行
			cin>>b[i][j];       //输入
			if(b[i][j]%2==0) s+=1;  //输入的同时判定奇偶(s为偶数数量)
			else o+=1;            //(o为奇数数量)
		}
	}
	cout<<o<<" "<<s;          //输出数量(注意顺序)
	return 0;		
}

三.零碎知识

接下来的知识,一些经验丰富的程序员可能说:太低级了

但我要让初学者们了解更多知识,所以我会讲一讲.

1.简单的进制转换 

我们先来学关于十进制与二进制的转换

a.十进制转二进制 

第一步,将需要转换的十进制一直短除2,除到一为止,把所有余数都标在旁边(余数只会有1或0)

图解(以22为例) :

 第二步,从下往上,把你标的余数写出来,这就是它的二进制

图解: 

b.二进制转十进制

tips:十进制变量名为m.

 从右往左看,如果从右往左数第n个是1,就给m加上2的n-1次方,加完后,m就是十进制了

还是以二进制10110为例:

10110

从右往左第1个,是0,不加      

m=0 

10110

从右往左第2个,是1,加2^(2-1)=2^1=2,即加2      

m=2

 10110

从右往左第3个,是1,加2^(3-1)=2^2=4,即加4         

m=6 

10110

从右往左第4个,是0,不加      

m=6

 10110

从右往左第5个,是1,加2^(5-1)=2^4=16,即加16        

m=22

好了,结束.

2.简单的函数

a.函数简介 

函数是一种将一段代码封装起来并命名的方式。函数可以接受输入参数,并根据参数执行一系列的操作,然后返回输出结果。函数的主要用途包括:

1. 代码的重用性:将一段经常使用的代码封装成函数,可以在程序中多处调用,避免重复编写相同的代码。
2. 代码的模块化:将复杂的问题拆解成多个函数,每个函数负责解决其中的一个子问题,提高代码的可读性和可维护性。
3. 提高代码的抽象层次:通过函数的名称和参数,可以更好地理解代码的逻辑和功能。
4. 提高代码的可测试性:由于函数具有确定的输入和输出,可以更方便地对函数进行单元测试,确保函数的正确性。
5. 提高程序的性能:通过将一些频繁执行的代码封装成函数,可以减少重复计算的次数,提高程序的执行效率。

总之,函数是一种将代码进行组织和重用的工具,能够提高代码的可读性、可维护性和可扩展性,提高程序的复用性和性能

在C++中,可以编写一个简单的函数来计算从1加到n的和。以下是一个示例代码:

#include <iostream>
int sum(int n) {
    int sum = 0;
    for (int i = 1; i <= n; ++i) {
        sum += i;
    }
    return sum;
}               // 函数定义

int main() {
    int n;
    cout << "请输入一个正整数 n: ";
    cin >> n;

    // 调用函数并输出结果
    int result = sum(n);
    cout << "从1加到" << n << "的和是: " << result << endl;

    return 0;
}

这个程序可以处理任何正整数 n,并正确计算从1加到n的和。

b.例题 

歌德巴赫猜想

内存限制:16 MB

时间限制:1.000 s

 题目描述

任意一个大于等于4的偶数都可以拆分为两个素数之和。

输入

一个整数n( 4 <= n <= 200 )

输出

将偶数n拆分为2个质数之和,列出所有方案

样例输入
10
样例输出
4=2+2
6=3+3
8=3+5
10=3+7
10=5+5
分析 

需要如下几个函数:

1.首先要找出4-200中的所有素数

2.遍历所有素数,寻找合适的数对

代码 
#include <iostream>
#include <cstdio>
using namespace std;
int n,a[100]; 
int x;
void find(){
	for(int i=3;i<=200;i+=2){
		for(int j=2;j<i;j++){
			 if(i%j==0) break;
			 else if(j==i-1) a[x]=i,x++; 
		} 
	} 
} 
void dict(int a,int b){
	if(a<=b and a+b==n) cout<<n<<"="<<a<<"+"<<b<<endl; 
} 
int main(){
	cin>>n;
	find();
	for(int i=0;i<=x;i++){
		for(int j=0;j<=x;j++){
			dict(a[i],a[j]); 
		}
	} 
	return 0;
}

四.冒泡排序

1.简介

冒泡排序(Bubble Sort)是最简单和最通用的排序方法,其基本思想是:在待排序的一组数中,将相邻的两个数进行比较,若前面的数比后面的数大就交换两数,否则不交换;如此下去,直至最终完成排序。由此可得,在排序过程中,大的数据往下沉,小的数据往上浮,就像气泡一样,于是将这种排序算法形象地称为冒泡排序

2.原理 

假定序列中有n个数,要进行从小到大的排序。若参与排序的数组元素共有n个,则需要n-1轮排序。在第i轮排序中,从左端开始,相邻两数比较大小,若反序则将两者交换位置,直到比较第n+1-i个数为止。第1个数与第2个数比较,第2个数和第3个数比较,一直到第n-i个数与第n+1-i个数比较,一共处理 n-i次。此时,第n+1-i个位置上的数已经有序,后续就不需要参加以后的排序。

 3.时间复杂度

时间复杂度是用于衡量算法运行时间随输入规模增长而变化的趋势的指标。它不关注具体的执行时间,而是关注操作次数的增长率,通常用大O符号(O)表示。

大O符号(O) 
   表示算法的最坏情况时间复杂度,即上界。例如:
   O(1):常数时间(如数组访问)。
   O(n):线性时间(如单层循环)。
   O(n²):平方时间(如双层嵌套循环)。
   O(log n):对数时间(如二分查找)。
   O(2ⁿ):指数时间(如递归斐波那契)。

其他符号  
   Ω(Omega):下界(最优情况)。
   Θ(Theta):紧确界(同时为O和Ω)。

冒泡排序最好的时间复杂度为O(n)

冒泡排序的最坏时间复杂度为O(n^{2})

因此冒泡排序总的平均时间复杂度为O(n^{2}

4.示例代码 

#include <iostream>
#include <cstdio>
using namespace std;
const int N=1e5+1;
int n,a[N],in; 
void PrintArray(int a[],int n){
	for(int i=1;i<=n;i++){
		printf("%d ",a[i]);
	} 
} 
int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]); 
	}
	for(int i=1;i<=n-1;i++){
		bool flag=true;
		for(int j=1;j<=n-1;j++){
			if(a[j]>a[j+1]) swap(a[j],a[j+1]),flag=false;
		} 
		if(flag) break; 
	} 
	PrintArray(a,n);
	return 0;
}

好了,今天的教程就到这里,如果喜欢,一定要点赞收藏,关注博主,我们下篇博客不见不散!

下节预告

1.更多排序

2.struct 结构体

3.高精度加法

还有一些知识点,博主看情况发

把你想学的打在评论区,博主尽量教你!!! 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值