ACM算法竞赛入门——C++基础语法(匠心之作,2.5万字总结,0基础教学,纯干货)建议收藏!!!

2 篇文章 0 订阅

xcx:主流语言这么多,为什么acm算法竞赛要用C++呢?

shy:C++在竞赛中实现算法和数据结构时具有更高的执行效率,对于一些需要处理大量数据和复杂算法的竞赛题目来说,C++ 能够提供更快的执行速度和更低的资源消耗,这对于算法竞赛中的性能要求至关重要。

hwjw:除此之外,C++还有什么其他的优点吗?

shy:C++ 提供了丰富的标准库,其中包括对数组、字符串、容器(如 vector、set、map 等)、算法(如排序、搜索等)等常用数据结构和算法的支持。这些标准库功能强大且经过优化,使得在算法竞赛中能够更快速地实现问题的解决方案。

xcx、hwjw:WOW!原来用C++打算法竞赛这么爽啊,那我们要好好学习C++基础语法!ヾ(≧▽≦*)o

1. 初识C++

1.1 第一个C++程序——输出"Hello world"

#include<iostream>			//标准输入输出流库,可以在程序中使用std::cout、std::cin等对象来进行输入输出操作
using namespace std;		//告诉编译器使用std命名空间中的名称,而不需要为它们加上std::前缀。例如,你可以直接写cout而不是std::cout。
int main()				//主函数,程序的主入口点。当你运行一个C++程序时,操作系统会调用这个main()函数,从而启动你的程序。
{
    cout << "Hello world"; 	//cout用于输出数据到控制台
    return 0;				//表示程序成功地执行完毕,并返回给操作系统一个状态码0,表示没有错误。
}

输出结果如下:

Hello world

1.2 注释

作用:在代码中加一些说明和解释,方便自己或其他人阅读代码。编译器在编译代码时,会忽略注释的内容。

种类

1.单行注释// 注释信息

2.多行注释/* 注释信息 */

//这是单行注释
/*
这是多行注释
这是多行注释
这是多行注释
*/

1.3 变量

作用:给一段指定的内存空间起名,方便操作这段内存

语法数据类型 变量名 = 初始值;

#include<iostream>
using namespace std;
int main()
{
	int a = 10;		//把a赋值为10
    cout << "a=" << a << endl;
    return 0;
}

输出结果如下:

a=10

变量的值可以修改,可以反复给一个变量赋值:

#include<iostream>
using namespace std;
int main()
{
    int a = 10;		//把a赋值为10
    a = 20;			//把a赋值为20
    a = 30;			//把a赋值为30
    cout << "a=" << a << endl;
    return 0;
}

输出结果如下:

a=30

1.4 常量

作用:用于记录程序中不可更改的数据

C++定义常量两种方法

​ 1.#define宏常量#define 常量名 常量值

​ 2.const修饰的变量const 数据类型 常量名 = 常量值;(注意分号)

Tips:算法竞赛中一般把较大的数组范围上限定义为N,例如:const long long N = 1e9+10;(一般都+10防止数组溢出)

示例:

#include<iostream>
#define id 20222245			//1.宏常量
using namespace std;
int main()
{
    cout<<"学生的id号为:"<<id<<endl;
    //id=20222246;	//报错,常量值不可修改
    
    const int age = 20;		//2.const修饰的变量
    cout<<"学生的年龄为:"<<age<<endl;
    //age = 21;	//报错,常量值不可修改
    
    return 0;
}

1.5 关键字

作用:关键字是C++中预先保留的单词

在定义变量或常量时,不要使用关键字

C++的关键字介绍

1.6 标识符命名

作用:C++中给变量、常量命名时,要遵循以下原则

  • 标识符不能是关键字

  • 标识符只由数字、字母、下划线组成

  • 第一个字符必须是字母或下划线 (不能是数字)

  • 标识符中区分大小写

  • 不能以中文命名(这里与Python不同)

    Tips:命名原则应见名知意,方便自己和他人阅读

2. 数据类型

C++在创建一个变量和常量时,必须要指出相应的数据类型,否则不能给变量分配内存

2.1 整型

作用:整型变量表示的是整数类型的数据

表示整型类型的方式,区别在于内存空间和可表示数的取值范围不同:

数据类型占用空间取值范围精确范围
short2Byte-215~215-1-32768~32767
int4Byte-231~231-1-2147483648~2147483647
longWindows:4Byte,Linux:4Byte(32位),8Byte(64位)-231~231-1-2147483648~2147483647
long long8Byte-263~263-1-9223372036854775808~9223372036854775807

Tips:算法竞赛中最常用的是 intlong long,int一般只能存下9位数,long long一般只能存下18位数,超长度就需要使用字符串string进行高精度处理

2.2 sizeof关键字

作用:利用sizeof关键字可以统计数据类型所占内存空间大小

语法sizeof(数据类型 或 变量)

#include<iostream>
using namespace std;
int main()
{
    cout<<"short 类型所占内存空间为:"<<sizeof(short)<<endl;
    cout<<"int 类型所占内存空间为:"<<sizeof(int)<<endl;
    cout<<"long 类型所占内存空间为:"<<sizeof(long)<<endl;
    cout<<"long long 类型所占内存空间为:"<<sizeof(long long)<<endl;
    
    return 0;
}

输出结果如下:

short 类型所占内存空间为:2
int 类型所占内存空间为:4
long 类型所占内存空间为:4
long long 类型所占内存空间为:8

或者直接使用sizeof(变量名)来统计占用的内存空间大小

#include<iostream>
using namespace std;
int main()
{
    int a = 10;
    cout<<"变量a所占的内存空间大小为:"<<sizeof(a)<<endl;
    
    return 0;
}

输出结果如下:

变量a所占的内存空间大小为:4

2.3 浮点型(实型)

作用:用于表示小数

浮点型变量分为两种:

1.单精度float

2.双精度double

两者的区别在于表示的有效数字范围不同

数据类型占用空间有效数字范围
float4Byte7位
double8Byte15~16位

Tips:算法竞赛中一般使用double

#include<iostream>
using namespace std;
int main()
{
	float f1=3.14f;		//float定义的浮点数最后要加f,否则默认为double
    double d1=3.14;
    
    cout<<f1<<endl;
    cout<<d1<<endl;
    
    cout<<"float sizeof = "<<sizeof(f1)<<endl;
    cout<<"double sizeof = "<<sizeof(d1)<<endl;
    
    return 0;
}

输出结果如下:

3.14
3.14
float sizeof = 4
double sizeof = 8

2.4 科学计数法

语法: men(m,n均为int)表示mn

#include<iostream>
using namespace std;
int main()
{
    double d1 = 3e2;	//3 * 10 ^ 2 = 300
    cout<<"d1 = "<<d1<<endl;
    
    double d2 = 3e-2;	//3 * 10 ^ -2 = 0.03
    cout<<"d2 = "<<d2<<endl;
    
    return 0;
}

输出结果如下:

d1 = 300
d2 = 0.03

2.5 字符型

作用:字符型变量用于显示单个字符

语法char ch = 'a';

在显示字符型变量时,用单引号将字符括起来,不要用双引号(双引号表示字符串string)

单引号内只能有一个字符,不可以是字符串

C++中char只占1个字节

字符型变量是将对应的ASCII码放入存储单元

#include<iostream>
using namespace std;
int main()
{
	char ch='a';		
    cout<<ch<<endl;		//直接输出字符ch
    cout<<sizeof(char)<<endl;	//char只占1个字节
    
    cout<<(int)ch<<endl;	//把ch强转为ASCII码
    ch=97;		//给char用ASCII码赋值
    cout<<ch<<endl;		//输出的是char类型
    
    return 0;
}

输出结果如下:

a
1
97
a

ASCII码表如下:

img

Tips:算法竞赛中一般只需记住A(65),a(97)即可

2.6 转义字符

作用:表示一些不能显示出来的ASCII字符

Tips:算法竞赛中常用的转义字符有:\n \\ \t

\n:换行符,相当于endl

\t:水平制表符,默认占8位

\\:表示一个反斜杠字符’\’

#include<iostream>
using namespace std;
int main()
{
	cout<<"\\"<<endl;
    cout<<"\tHello"<<endl;
    cout<<"\n"<<endl;
    
    return 0;
}

输出结果如下:

\
        Hello

2.7 字符串型

作用:用于表示一串字符

两种风格

​ 1.C风格char 变量名[] = "字符串值"

#include<iostream>
using namespace std;
int main()
{
	char str[]="hello world";
	cout<<str<<endl;
	
	return 0;
}

输出结果如下:

hello world

2.C++风格string 变量名 = "字符串值"

#include<iostream>
#include<string>	//引入字符串的头文件
using namespace std;
int main()
{
	string str = "hello world";
    cout<< str <<endl;
    
    return 0;
}

输出结果如下:

hello world

Tips:算法竞赛中通常使用C++风格(string),string有很多高端的操作 (੭ˊᵕˋ)੭ଘ

2.8 布尔类型bool

作用:bool类型代表真或假的值

bool类型只有两个值:

true:真——1

false:假——0

bool类型占1个字节

#include<iostream>
using namespace std;
int main()
{
	bool flag = true;
    cout<<flag<<endl;	//1
    
    flag = false;
    cout<<false<<endl;	//0
    
    cout<<"sizeof bool = "<<sizeof(bool)<<endl;		//1
    
    return 0;
}

输出结果如下:

1
0
sizeof bool = 1

2.9 数据的输入

作用用于从键盘获取数据

关键字:cin

语法cin>>变量

#include<iostream>
using namespace std;
int main()
{
	//整型
    int num = 0;
    cin>>num;
    cout<<num<<endl;
    
    //浮点型
    double d = 0;
    cin>>d;
    cout<<d<<endl;
    
    //字符型
    char ch = 0;
    cin>>ch;
    cout<<ch<<endl;
    
    //字符串型
    string str;
    cin>>str;
    cout<<str<<endl;
    
    //布尔类型
    bool flag = true;
    cin>>flag;
    cout<<flag<<endl;
    
    return 0;
}

3. 运算符

分类

运算符

3.1 算术运算符

作用:用于处理四则运算

运算符名称
+正号
-负号
+
-
*
/
%取模
++前置递增
++后置递增
前置递减
后置递减

加减乘:

#include<iostream>
using namespace std;
int main()
{
	int a=10;
    int b=3;
    
    cout<<a+b<<endl;	//13
    cout<<a-b<<endl;	//7
    cout<<a*b<<endl;	//30
    
    return 0;
}

除:

#include<iostream>
using namespace std;
int main()
{
	int a1=10,b1=3;
    cout<<a1/b1<<endl;		//3,两个整数相除依然是整数
    
    int a2=10,b2=20;
    cout<<a2/b2<<endl;		//0
    
    int a3=10,b3=0;
    //cout<<a3/b3<<endl;	//error,除数不能为0
    
    double d1=0.5,d2=0.25;
    cout<<d1/d2<<endl;		//2
    
    return 0;
}

取模:只有整型变量才能取模

#include<iostream>
using namespace std;
int main()
{
	cout<<10%3<<endl;		//1
    cout<<10%20<<endl;		//10
    //cout<<10%0<<endl;		//取模运算,除数不能为0
    //cout<<3.14%1.1<<endl;	//小数不能取模
    
    return 0;
}

递增递减:

#include<iostream>
using namespace std;
int main()
{
	//后置递增
    int a=10;
    a++;	//a=a+1;
    cout<<a<<endl;	//11
    
    //前置递增
    int b=10;
    ++b;	//b=b+1;
    cout<<b<<endl;	//11
    
    //后置递减
    int c=10;
    c--;	//c=c-1;
    cout<<c<<endl;	//9
    
    //前置递减
    int d=10;
    --d;	//d=d-1;
    cout<<d<<endl;	//9
    
    //区别
    //前置递增先对变量进行++,再计算表达式
    int a1=10;
    int b1=++a1*10;	//(10+1)*10=110
    cout<<b1<<endl;
    //后置递增先计算表达式,后对变量进行++
    int a2=10;
    int b2=a2++*10;	//10*10=100
    cout<<b2<<endl;
    //前置递减先对变量进行--,再计算表达式
    int a3=10;
    int b3=--a3*10;	//(10-1)*10=90
    cout<<b3<<endl;
    //后置递减先计算表达式,后对变量进行--
    int a4=10;
    int b4=a4--*10;	//10*10=100
    cout<<b4<<endl;
}

3.2 赋值运算符

作用:用于将表达式的值赋给变量

运算符名称
=赋值
+=加等于
-=减等于
*=乘等于
/=除等于
%=模等于
#include<iostream>
using namespace std;
int main()
{
    //=
    int a=10;
    a=100;
    cout<<"a="<<a<<endl;	//a=100
    
    //+=
    a=10;
    a+=2;	//a=a+2;
    cout<<"a="<<a<<endl;	//a=12
    
    //-=
    a=10;
    a-=2;	//a=a-2;
    cout<<"a="<<a<<endl;	//a=8
    
    //*=
    a=10;
    a*=2;	//a=a*2;
    cout<<"a="<<a<<endl;	//a=20
    
    ///=
    a=10;
    a/=2;	//a=a/2;
    cout<<"a="<<a<<endl;	//a=5
    
    //%=
    a=10;
    a%=2;	//a=a%2;
    cout<<"a="<<a<<endl;	//a=0
    
    return 0;
}

3.3 比较运算符

作用:用于表达式的比较,并返回一个真值或假值

运算符名称
==相等于
!=不等于
<小于
>大于
<=小于等于
>=大于等于
#include<iostream>
using namespace std;
int main()
{
    int a=20;
    int b=20;
    
    cout<<(a==b)<<endl;	//0 假
    cout<<(a!=b)<<endl;	//1 真
    cout<<(a>b)<<endl;	//0 假
    cout<<(a<b)<<endl;	//1 真
    cout<<(a>=b)<<endl;	//0 假
    cout<<(a<=b)<<endl;	//1 真
    
    return 0;
}

3.4 逻辑运算符

作用:用于根据表达式的值返回真值或假值

运算符名称语法
!!a
&&a&&b
||a||b

1.非:假变真,真变假

真值表

a!a
01
10
#include<iostream>
using namespace std;
int main()
{
	int a=10;
    cout<<!a<<endl;		//0
    cout<<!!a<<endl;	//1
    
    return 0;
}

2.与:同真为真,其余为假

真值表

aba&&b
000
010
100
111
#include<iostream>
using namespace std;
int main()
{
    int a=10;
    int b=10;
    cout<<(a&&b)<<endl;		//1
    
    a=10;
    b=0;
    cout<<(a&&b)<<endl;		//0
    
    a=0;
    b=0;
    cout<<(a&&b)<<endl;		//0
    
    return 0;
}

3.或:同假为假,其余为真

真值表

aba||b
000
011
101
111
#include<iostream>
using namespace std;
int main()
{
    int a=10;
    int b=10;
    cout<<(a||b)<<endl;		//1
    
    a=10;
    b=0;
    cout<<(a||b)<<endl;		//1
    
    a=0;
    b=0;
    cout<<(a||b)<<endl;		//0
    
    return 0;
}

4. 程序流程结构

C++基本运行结构:顺序结构、选择结构、循环结构

  • 顺序结构:程序顺序执行,不发生跳转
  • 选择结构(条件结构):依据条件是否满足,有选择地执行相应代码
  • 循环结构:依据条件是否满足,循环多次执行某段代码

4.1 选择结构

4.1.1 if语句

1.单行if语句if(条件){条件满足执行的语句}

#include<iostream>
using namespace std;
int main()
{
    //输入一个分数,如果分数大于等于95分,则视为获得了保研资格
    
	int score=0;
    cout<<"请输入学生分数:"<<endl;
    cin>>score;
    
    cout<<"学生分数为:"<<score<<endl;
    
    if (score>=95)
    {
        cout<<"恭喜你获得了保研资格!!!"<<endl;
    }
    
    return 0;
}

2.多行if语句if(条件){条件满足执行的语句} else{条件不满足时执行的语句}

#include<iostream>
using namespace std;
int main()
{
    int score=0;
    cout<<"请输入学生分数:"<<endl;
    cin>>score;
    
    cout<<"学生分数为:"<<score<<endl;
    
    if(score>=95)
    {
        cout<<"恭喜你获得了保研资格!!!ヾ(≧▽≦*)o"<<endl;
    }
    else
    {
        cout<<"很遗憾没有获得保研资格,好好准备考研吧!!!╥﹏╥..."<<endl;
    }
    
    return 0;
}

3.多条件if语句if(条件1){条件1满足执行的语句} else if(条件2){条件2满足执行的语句} else{都不满足执行的语句}

#include<iostream>
using namespace std;
int main()
{
	int score=0;
    cout<<"请输入学生分数:"<<endl;
    cin>>score;
    
    cout<<"学生分数为:"<<score<<endl;
    
    if(score==100)
    {
        cout<<"学生绩点为5.0";
    }
    else if(score>=95)
    {
        cout<<"学生绩点为4.5";
    }
    else if(score>=90)
    {
        cout<<"学生绩点为4.0";
    }
    else if(score>=85)
    {
        cout<<"学生绩点为3.5";
    }
    else if(score>=80)
    {
        cout<<"学生绩点为3.0";
    }
    else if(score>=75)
    {
        cout<<"学生绩点为2.5";
    }
    else if(score>=70)
    {
        cout<<"学生绩点为2.0";
    }
    else if(score>=65)
    {
        cout<<"学生绩点为1.5";
    }
    else if(score>=60)
    {
        cout<<"学生绩点为1.0";
    }
    else
    {
        cout<<"挂了,准备补考吧!!!";
    }
    
    return 0;
}

Tips:在算法竞赛中,{}内执行语句只有一句时,通常可以省略{},例如:

#include<iostream>
using namespace std;
int main()
{
	int score=0;
    cout<<"请输入学生分数:"<<endl;
    cin>>score;
    
    cout<<"学生分数为:"<<score<<endl;
    
    if(score==100)cout<<"学生绩点为5.0";
    else if(score>=95)cout<<"学生绩点为4.5";
    else if(score>=90)cout<<"学生绩点为4.0";
    else if(score>=85)cout<<"学生绩点为3.5";
    else if(score>=80)cout<<"学生绩点为3.0";
    else if(score>=75)cout<<"学生绩点为2.5";
    else if(score>=70)cout<<"学生绩点为2.0";
    else if(score>=65)cout<<"学生绩点为1.5";
    else if(score>=60)cout<<"学生绩点为1.0";
    else cout<<"挂了,准备补考吧!!!";
    
    return 0;
}

if语句的嵌套:在if语句中,可以使用嵌套语句达到更精准的条件判断

例如:

用户输入学生的分数:

如果分数大于等于95分,则认为该学生获得了保研资格。如果分数小于95分,则认为该学生没有获得保研资格。

在保研的分数中,如果等于100分,则绩点为5.0;如果分数95~100分,则绩点为4.5。

在未保研的分数中,如果90~95分,则绩点为4.0;如果85~90分,则绩点为3.5;如果80~85分,则绩点为3.0;如果75~80分,则绩点为2.5;如果70~75分,则绩点为2.0;如果65~70分,则绩点为1.5;如果60~65分,则绩点为1.0;如果小于60分,则挂科。

#include<iostream>
using namespace std;
int main()
{
	int score=0;
    cout<<"请输入学生分数:"<<endl;
    cin>>score;
    
    cout<<"学生分数为:"<<score<<endl;
    
    if(score>=95)
    {
        cout<<"恭喜你获得了保研资格!!!ヾ(≧▽≦*)o"<<endl;
        if(score==100)cout<<"学生绩点为5.0";
        else cout<<"学生绩点为4.5";
    }
    else
    {
        cout<<"很遗憾没有获得保研资格,好好准备考研吧!!!╥﹏╥..."<<endl;
        if(score>=90)cout<<"学生绩点为4.0";
        else if(score>=85)cout<<"学生绩点为3.5";
    	else if(score>=80)cout<<"学生绩点为3.0";
    	else if(score>=75)cout<<"学生绩点为2.5";
    	else if(score>=70)cout<<"学生绩点为2.0";
    	else if(score>=65)cout<<"学生绩点为1.5";
    	else if(score>=60)cout<<"学生绩点为1.0";
    	else cout<<"挂了,准备补考吧!!!";
    }
    
    return 0;
}
4.1.2 条件运算符(三目运算符)

作用:实现简单的判断

语法表达式1 ? 表达式2 : 表达式3

说明:如果表达式1为真,执行表达式2,并返回表达式2的结果;如果表达式1为假,执行表达式3,并返回表达式3的记结果

#include<iostream>
using namespace std;
int main()
{
	int a=10;
    int b=20;
    int c=0;
    
    c=a>b?a:b;
    cout<<"c="<<c<<endl;		//c=20
    
    //三目运算符返回的是变量,可以继续赋值
   	
    (a>b?a:b)=100;
    
    cout<<"a="<<a<<endl;		//a=10
    cout<<"b="<<b<<endl;		//b=100
    cout<<"c="<<c<<endl;		//c=20
    
    return 0;

}
4.1.3 switch语句

作用:执行多条分支语句

语法

switch(表达式)//------------------------------->此处表达式类型只能是int型或char型		
{
	case 结果1:执行语句;break;//---------------->如果没有break,程序会一直向下执行下去
	case 结果2:执行语句;break;
	......
	default:执行语句;break;
}

案例:

#include<iostream>
using namespace std;
int main()
{
	//根据等级对学生进行评价
    //A:优秀
    //B:良好
    //C:一般
    //D:及格
    //其他:不及格
    
    char grade=0;
    cout<<"请给出学生等级"<<endl;
    cin>>grade;
    
    switch(grade)
    {
        case 'A':
            cout<<"优秀"<<endl;
            break;
        case 'B':
            cout<<"良好"<<endl;
            break;
        case 'C':
            cout<<"一般"<<endl;
            break;
        case 'D':
            cout<<"及格"<<endl;
            break;
        default:
            cout<<"不及格"<<endl;
    }
    
    return 0;
}

与if语句相比,对于多条件判断时,switch结构清晰,执行效率高,缺点是switch不可以判断区间

4.2 循环结构

4.2.1 while循环

作用:满足循环循环条件,执行循环语句

语法while(循环条件){循环语句}

解释:循环条件为真,执行循环语句

#include<iostream>
using namespace std;
int main()
{
	int n=0;
    while(n<10)
    {
        cout<<n<<" ";		//0 1 2 3 4 5 6 7 8 9
        n++;
    }
    
    return 0;
}

执行循环语句时,程序必须提供跳出循环的出口,否则会出现死循环,例如:

#include<iostream>
using namespace std;
int main()
{
	int n=0;
    while(1)
    {
        cout<<n<<" ";
        n++;
    }
    
    return 0;
}

Tips:算法竞赛中TLE(超出时间限制,Time Limit Exceed)可能是因为程序中有死循环,或者时间复杂度过高。

Tips:算法竞赛中switch语句一般用于多组数据的输入,下面给出三个例子:

e.g.1

输入包含多组数据,每组数据输入一行,包含两个整数

对于每组数据输出一行包含一个整数表示两个整数的和

Input

1 2
3 4

Output

3
7
#include<iostream>
using namespace std;
int main()
{
    int a,b;
    while(cin>>a>>b)
    {
        cout<<a+b<<endl;
    }
    return 0;
}

e.g.2

第一行输入一个数据组数n

接下来n行每行输入两个整数

对于每组数据计算a+b的值

Input

2
1 1
2 2

Output

2
4
#include<iostream>
using namespace std;
int main()
{
    int n;
    int a,b;
    cin>>n;
    while(n--)
    {
        cin>>a>>b;
        cout<<a+b<<endl;
    }
    return 0;
}

e.g.3

多组数据,每组输入两个整数,当两个整数都为0时表示输入结束

对于每组数据输出两个整数的和

Input

1 1
2 2
0 0

Output

2
4
#include<iostream>
using namespace std;
int main()
{
    int a,b;
    while(cin>>a>>b&&(a!=0&&b!=0))
    {
        cout<<a+b<<endl;
    }
    return 0;
}
4.2.2 do…while循环

作用:满足循环循环条件,执行循环语句

语法do{循环语句}while(循环条件);

解释:先执行一次循环语句,再判断循环条件

#include<iostream>
using namespace std;
int main()
{
	int n=0;
    do
    {
        cout<<n<<" ";	//0 1 2 3 4 5 6 7 8 9
        n++;
    }while(n<10);
    
    return 0;
}
4.2.3 for循环

作用:满足循环循环条件,执行循环语句

语法for(起始表达式 ; 条件表达式 ; 末尾循环体){循环语句;}

#include<iostream>
using namespace std;
int main()
{
	for(int i=0;i<10;i++)
    {
        cout<<i<<" ";		//0 1 2 3 4 5 6 7 8 9
    }
    
    return 0;
}

也可以写成以下形式:

#include<iostream>
using namespace std;
int main()
{
	int i=0;
    for(;;)
    {
        if(i>=10)
        {
            break;
        }
        cout<<i<<" ";	//0 1 2 3 4 5 6 7 8 9
        i++;
    }
    return 0;
}

Tips:算法竞赛中经常使用到for循环

4.2.4 嵌套循环

说明:在循环体中再嵌套一层循环

例如输出一个10*10的加号阵

#include<iostream>
using namespace std;
int main()
{
	for(int i=0;i<10;i++)	//行循环
    {
        for(int j=0;j<10;j++)	//列循环
        {
            cout<<"+ ";
        }
        cout<<endl;		//列循环结束一轮,换行,再进行列循环
    }
    return 0;
}

输出如下:

+ + + + + + + + + +
+ + + + + + + + + +
+ + + + + + + + + +
+ + + + + + + + + +
+ + + + + + + + + +
+ + + + + + + + + +
+ + + + + + + + + +
+ + + + + + + + + +
+ + + + + + + + + +
+ + + + + + + + + +

4.3 跳转语句

4.3.1 break语句

作用:跳出选择结构或循环结构

使用时机:

1.switch条件语句:终止case并跳出switch

2.循环语句:跳出当前的循环语句

3.嵌套循环:跳出最近的内层循环

e.g.1

#include<iostream>
using namespace std;
int main()
{
	//根据等级对学生进行评价
    //A:优秀
    //B:良好
    //C:一般
    //D:及格
    //其他:不及格
    
    char grade=0;
    cout<<"请给出学生等级"<<endl;
    cin>>grade;
    
    switch(grade)
    {
        case 'A':
            cout<<"优秀"<<endl;
            break;
        case 'B':
            cout<<"良好"<<endl;
            break;
        case 'C':
            cout<<"一般"<<endl;
            break;
        case 'D':
            cout<<"及格"<<endl;
            break;
        default:
            cout<<"不及格"<<endl;
    }
    
    return 0;
}

e.g.2

#include<iostream>
using namespace std;
int main()
{
	for(int i=0;i<10;i++)
    {
        if(i==5)
        {
            break;
        }
        cout<<i<<" ";		//0 1 2 3 4
    }
    
    return 0;
}

e.g.3

#include<iostream>
using namespace std;
int main()
{
	for(int i=0;i<10;i++)
    {
        for(int j=0;j<10;j++)
        {
            if(j==5)
            {
                break;
            }
            cout<<"*"<<" ";
        }
        cout<<endl;
    }
    
    return 0;
}
4.3.2 continue语句

作用:循环语句中,跳出本次循环中余下尚未执行的语句,继续执行下一次循环

#include<iostream>
using namespace std;
int main()
{
	for(int i=0;i<100;i++)
	{
		if(i%2==0)
		{
			continue;
		}
        cout<<i<<" ";	//1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 41 43 45 47 49 51 53 55 57 59 61 63 65 67 69 71 73 75 77 79 81 83 85 87 89 91 93 95 97 99
	}
    
    return 0;
}
4.3.3 goto语句

作用:可以无条件跳转语句

语法goto标记

解释:跳转到标记位置

#include<iostream>
using namespace std;
int main()
{
    cout<<1<<endl;
    goto FLAG;
    cout<<2<<endl;
    cout<<3<<endl;
    cout<<4<<endl;
    FLAG:
    cout<<5<<endl;
    
    return 0;
}

输出:

1
5

5. 数组

5.1 特点

1.数组中每一个数据元素都是相同的数据类型

2.数组是由连续的内存位置组成的

3.数组元素下标从0开始索引

5.2 一维数组

5.2.1 定义方式

1.数据类型 数组名[len];

2.数据类型 数组名[len] = {value1,value2,...};

3.数据类型 数组名[] = {value1,value2,...};

#include<iostream>
using namespace std;
int main()
{
	//定义1
    int array[10];
    
    //用数组下标直接赋值
    array[0]=1;
    array[1]=2;
    array[2]=3;
    
    //利用下标输出
    cout<<array[0]<<" ";
    cout<<array[1]<<" ";
    cout<<array[2]<<" ";
    cout<<endl;
    
    //————————————————————————————————————————————————————
    //定义2
    int array1[10]={1,2,3};		//{}内数据不足10个,其余数据自动补0
    for(int i=0;i<10;i++)cout<<array1[i]<<" ";
    cout<<endl;
    
    //————————————————————————————————————————————————————
    //定义3
    int array2[]={1,2,3,4,5,6,7,8,9,10};
    for(int i=0;i<10;i++)cout<<array2[i]<<" ";
    
    return 0;
}

输出结果如下:

1 2 3
1 2 3 0 0 0 0 0 0 0
1 2 3 4 5 6 7 8 9 10
5.2.2 统计数组占用内存大小
#include<iostream>
using namespace std;
int main()
{
	int array[10]={1,2,3,4,5,6,7,8,9,10};
    
    cout<<"数组所占内存空间大小为:"<<sizeof(array)<<endl;			//40
    cout<<"每个元素所占内存空间为:"<<sizeof(array[0])<<endl;		//4
    cout<<"数组元素个数为:"<<sizeof(array)/sizeof(array[0])<<endl;		//10
    
    return 0;
}
5.2.3 获取内存中的地址
#include<iostream>
using namespace std;
int main()
{
	int array[10]={1,2,3,4,5,6,7,8,9,10};
	
	cout<<"数组首地址为:"<<(int)array<<endl;	//此处转为十进制了
	cout<<"数组中第一个元素地址为:"<<(int)&array[0]<<endl;
	cout<<"数组中第二个元素地址为:"<<(int)&array[1]<<endl;
	
	return 0;
}
5.2.4 一维数组的输入和输出

Tips:算法竞赛中通常要用到一维数组的输入和输出

第一行输入一个整数n

第二行输入n个数

输出这n个数

#include<iostream>
using namespace std;
const int N = 10;
int arr[N];
int main()
{
	int n;
	cin>>n;
    for(int i=0;i<n;i++)
        cin>>arr[i];
    for(int i=0;i<n;i++)
        cout<<arr[i]<<" ";
    
    return 0;
}

5.3 二维数组

5.3.1 定义方式

1.数据类型 数组名[行数][列数];

2.数据类型 数组名[行数][列数]={{数据1,数据2},{数据3,数据4}};

3.数据类型 数组名[行数][列数]={数据1,数据2,数据3,数据4};

4.数据类型 数组名[][列数]={数据1,数据2,数据3,数据4};

#include<iostream>
using namespace std;
int main()
{
    //定义1
	int array1[2][3];
    array1[0][0]=1;
    array1[0][1]=2;
    array1[0][2]=3;
    array1[0][3]=4;
    array1[0][4]=5;
    array1[0][5]=6;
    
    for(int i=0;i<2;i++)
    {
        for(int j=0;j<3;j++)
        {
            cout<<array1[i][j]<<" ";	
        }
        cout<<endl;
    }
    //----------------------------------------------
    //定义2
    int array2[2][3]=
    {
        {1,2,3},
        {4,5,6}
    };
    
    for(int i=0;i<2;i++)
    {
        for(int j=0;j<3;j++)
        {
            cout<<array2[i][j]<<" ";
        }
        cout<<endl;
    }
    //----------------------------------------------
    //定义3
    int array3[2][3]={1,2,3,4,5,6};
    
    for(int i=0;i<2;i++)
    {
        for(int j=0;j<3;j++)
        {
            cout<<array3[i][j]<<" ";
        }
        cout<<endl;
    }
    //----------------------------------------------
    //定义4
    int array4[][3]={1,2,3,4,5,6};
    
    for(int i=0;i<2;i++)
    {
        for(int j=0;j<3;j++)
        {
            cout<<array4[i][j]<<" ";
        }
        cout<<endl;
    }
    
    return 0;
}

输出均为:

1 2 3
4 5 6
5.3.2 统计数组占用内存大小
#include<iostream>
using namespace std;
int main()
{
	int array[2][3]=
    {
        {1,2,3},
        {4,5,6}
    };
    
    cout<<"二维数组大小:"<<sizeof(array)<<endl;				//24
    cout<<"二维数组一行大小:"<<sizeof(array[0])<<endl;			//12
    cout<<"二维数组元素大小:"<<sizeof(array[0][0])<<endl;		//4
    
    cout<<"二维数组行数:"<<sizeof(array)/sizeof(array[0])<<endl;		//2
    cout<<"二维数组列数:"<<sizeof(array[0])/sizeof(array[0][0])<<endl;	//3
    
    return 0;
}
5.3.3 获取内存中的地址
#include<iostream>
using namespace std;
int main()
{
	int array[2][3]=
    {
        {1,2,3},
        {4,5,6}
    };
    
    cout<<"二维数组首地址:"<<array<<endl;		//此处地址为十六进制
    cout<<"二维数组第一行地址:"<<array[0]<<endl;
    cout<<"二维数组第二行地址:"<<array[1]<<endl;
    
    cout<<"二维数组第一个元素地址:"<<&array[0][0]<<endl;
    cout<<"二维数组第二个元素地址:"<<&array[0][1]<<endl;
    
    return 0;
}
5.3.4 二维数组的输入和输出

Tips:算法竞赛中通常要用到二维数组的输入和输出

输入两个整数m,n

输入一个m*n的二维数组

输出这个二维数组

#include<iostream>
using namespace std;
const int N = 10;
int arr[N][N];
int main()
{
	int m,n;
    cin>>m>>n;
    for(int i=0;i<m;i++)
    {
        for(int j=0;j<n;j++)
        {
            cin>>arr[i][j];
        }
    }
    for(int i=0;i<m;i++)
    {
        for(int j=0;j<n;j++)
        {
            cout<<arr[i][j]<<" ";
        }
        cout<<endl;
    }
    
    return 0;
}

6. 函数

作用将一段经常使用的代码封装起来,减少重复代码

6.1 函数的定义

函数的定义一般由5部分构成:返回值类型函数名参数列表(传入函数的数据),函数体语句(函数执行语句),return表达式(返回数据)

语法

返回值类型 函数名(参数列表)
{
	函数体语句
	
	return表达式
}

e.g. 一个函数实现两个数相加

#include<iostream>
using namespace std;
int add(int num1,int num2)
{
    int sum=num1+num2;
    return sum;
}
int main()
{
    cout<<add(1,2);		//输出3,函数的调用,详见6.2
}

6.2 函数的调用

作用:使用定义好的函数

语法函数名(参数)

#include<iostream>
using namespace std;
int add(int num1,int num2)
{
    int sum=num1+num2;
    return sum;
}
int main()
{
	int a=10;
    int b=10;
    
    int sum=add(a,b);
    cout<<sum<<endl;		//20
    
    a=100;
    b=100;
    
    sum=add(a,b);
    cout<<sum<<endl;		//200
    
    return 0;
    
}

6.3 函数值传递

定义:值传递就是通过函数调用将实参传入形参

形参的变化并不影响实参

#include<iostream>
using namespace std;
void swap(int num1,int num2)		//void类型无需return返回值,详见6.4函数的样式分类
{
    cout<<"交换前:"<<endl;
    cout<<"num1 = "<<num1<<endl;
    cout<<"num2 = "<<num2<<endl;
    
    int temp = num1;
    num1 = num2;
    num2 = temp;
    
    cout<<"交换后:"<<endl;
    cout<<"num1 = "<<num1<<endl;
    cout<<"num2 = "<<num2<<endl;
}
int main()
{
	int a = 10;
    int b = 20;
    
    swap(a,b);	//形参的变化不影响实参
    cout<<"a = "<<a<<endl;
    cout<<"b = "<<b<<endl;
    
    return 0;
}

输出结果如下:

交换前:
num1 = 10
num2 = 20
交换后:
num1 = 20
num2 = 10
a = 10
b = 20

6.4 函数的样式分类

函数常见样式一般有四种:无参无返有参无返无参有返有参有返

#include<iostream>
using namespace std;

//无参无返
void fun1()
{
    //void a=10;	//不能创建变量,无法分配内存
    cout<<"这个是fun1"<<endl;
}
//-------------------------------------------------
//有参无返
void fun2(int a)
{
    cout<<"这个是fun2"<<endl;
    cout<<"a="<<a<<endl;
}
//-------------------------------------------------
//无参有返
int fun3()
{
    cout<<"这个是fun3"<<endl;
    return 10;
}
//-------------------------------------------------
//有参有返
int fun4(int a,int b)
{
    cout<<"这个是fun4"<<endl;
    int sum = a+b;
    return sum;
}

int main()
{
	fun1();
    fun2(10);
    cout<<fun3()<<endl;
    cout<<fun4(10,20)<<endl;
    
    return 0;
}

输出结果如下:

这个是fun1
这个是fun2
a=10
这个是fun3
10
这个是fun4
30

6.5 函数的声明

作用:告诉编译器函数名称及如何调用函数。

语法返回值类型 函数名(参数列表);

函数的声明可多次,函数的定义只有一次

#include<iostream>
using namespace std;

int sum(int a,int b);	//函数的声明
int sum(int a,int b);	//函数的声明可多次
int sum(int a,int b);	//函数的声明可多次

int main()
{
	cout<<sum(10,20);
    return 0;
}

int sum(int a,int b)	//函数声明之后可以再主函数后写函数的定义
{
    int sum=a+b;
    return sum;
}

7. 结构体

7.1 结构体概念

用户自定义的数据类型,允许用户存储不同的数据类型

7.2 结构体的定义

语法struct 结构体名{结构体成员列表};

创建变量方法:

  • struct 结构体名 变量名
  • struct 结构体名 变量名={value1,value2};
  • 定义结构体时创建变量
#include<iostream>
using namespace std;

//结构体的定义
struct student
{
    string name;
    int age;
    int score;
};
int main()
{
	//创建变量方法1
    struct student stu;	//"struct"关键字可省略
    
    stu.name = "xcx";	//结构体变量用操作符"."访问成员
    stu.age = 18;
    stu.score = 90;
    
    cout<<"name:"<<stu.name<<"  age:"<<stu.age<<"  score:"<<stu.score<<endl;
    //name:xcx  age:18  score:90
    
    return 0;
}
#include<iostream>
using namespace std;

//结构体的定义
struct student
{
    string name;
    int age;
    int score;
};
int main()
{
	//创建变量方法2
    struct student stu = {"hwjw",20,100};
    
    cout<<"name:"<<stu.name<<"  age:"<<stu.age<<"  score:"<<stu.score<<endl;
    //name:hwjw  age:20  score:100
    
    return 0;
}
#include<iostream>
using namespace std;

//结构体的定义
struct student
{
    string name;
    int age;
    int score;
}stu;
int main()
{
	stu.name = "shy";
    stu.age = 19;
    stu.score = 95;
    
    cout<<"name:"<<stu.name<<"  age:"<<stu.age<<"  score:"<<stu.score<<endl;
    //name:shy  age:19  score:95
    
    return 0;
}

7.3 结构体数组

作用:将自定义结构体放入到数组中方便维护

语法struct 结构体名 数组名[len] = {{},{},{},...,{}};

#include<iostream>
using namespace std;

//结构体的定义
struct student
{
    string name;
    int age;
    int score;
};

int main()
{
	struct student stu[3]=
    {
        {"xcx",18,90},
        {"hwjw",20,100},
        {"shy",19,90}
    };
    for(int i=0;i<3;i++)
    {
        cout<<"name:"<<stu[i].name<<"  age:"<<stu[i].age<<"  score:"<<stu[i].score<<endl;
    }
    
    return 0;
}

输出结果如下:

name:xcx  age:18  score:90
name:hwjw  age:20  score:100
name:shy  age:19  score:90

7.4 结构体数组的输入和输出

Tips:算法竞赛中通常会用到结构体数组的输入和输出

#include<iostream>
using namespace std;
struct student
{
    string  name;
    int age;
    int score;
}stu[3];
    
int main()
{
    //输入
	for(int i=0;i<3;i++)
    {
        cin>>stu[i].name>>stu[i].age>>stu[i].score;
    }
    //输出
    for(int i=0;i<3;i++)
    {
        cout<<"姓名:"<<stu[i].name<<"  年龄:"<<stu[i].age<<"  成绩:"<<stu[i].score<<endl;
    }
    
    return 0;
}

输入:

xcx 19 90
hwjw 20 100
shy 19 100

输出:

姓名:xcx  年龄:19  成绩:90
姓名:hwjw  年龄:20  成绩:100
姓名:shy  年龄:19  成绩:100

7.5 结构体嵌套结构体

例如:一个老师结构体中记录一个学生结构体

#include<iostream>
using namespace std;

//学生结构体
struct student
{
    string name;
    int age;
    int score;
};
//老师结构体
struct teacher
{
    string name;
    int age;
    int id;
    struct student stu;	//嵌套学生结构体
}tea;
    
int main()
{
	tea.name="shy";
    tea.age=19;
    tea.id=20222245;
    
    tea.stu.name="xcx";
    tea.stu.age=18;
    tea.stu.score=90;
    
    cout<<"教师姓名:"<<tea.name<<"  年龄:"<<tea.age<<"  职工号:"<<tea.id<<endl;
    cout<<"学生姓名:"<<tea.stu.name<<"  年龄:"<<tea.stu.age<<"  分数:"<<tea.stu.score;
    //教师姓名:shy  年龄:19  职工号:20222245
	//学生姓名:xcx  年龄:18  分数:90
    
    return 0;
}

7.6 结构体做函数参数

作用:将结构体作为参数向函数中传递

传递方式:值传递地址传递

算法竞赛基本不用,只做了解

#include<iostream>
using namespace std;

//定义结构体
struct student
{
    string name;
    int age;
    int score;
};

//值传递
void showStudent_v(student stu)
{
    stu.age = 18;
    cout<<"show函数中  姓名:"<<stu.name<<"  年龄:"<<stu.age<<"  分数:"<<stu.score<<endl;
}

//地址传递
void showStudent_s(student *stu)
{
    stu->age = 18;
    cout<<"show函数中  姓名:"<<stu->name<<"  年龄:"<<stu->age<<"  分数:"<<stu->score<<endl;
}

int main()
{
	student stu = {"shy",19,100};
    
    //值传递
    showStudent_v(stu);
    cout<<"main函数中  姓名:"<<stu.name<<"  年龄:"<<stu.age<<"  分数:"<<stu.score<<endl;
    
    //地址传递
    showStudent_s(&stu);
    cout<<"main函数中  姓名:"<<stu.name<<"  年龄:"<<stu.age<<"  分数:"<<stu.score<<endl;
    
    return 0;
}

输出结果如下:

show函数中  姓名:shy  年龄:18  分数:100
main函数中  姓名:shy  年龄:19  分数:100
show函数中  姓名:shy  年龄:18  分数:100
main函数中  姓名:shy  年龄:18  分数:100

不想修改主函数中的数据用值传递,想修改主函数中的数据用地址传递

7.7 结构体算法竞赛例题

题目: lcryin的排序题

题目描述:

lcryin已经在bodongli老师的c语言课堂上学了简单的冒泡排序,但是现在lcryin遇到了一个难题,他想知道在坐标系上的n个点到原点的距离的平方并将距离平方及其坐标从小到大输出,你能帮他解决这个问题嘛。

输入描述:

第一行有一个整数n,表示点的个数。(0<n<10)

接下来n行,每行有两个整数x,y表示这个点的坐标。(-1000000<x,y<1000000)

输出描述:

输出n行。

每行包含三个数x,y,dis2表示该点的坐标及其距离的平方。

示例:

输入

5
1 2
2 3
3 4
4 5
5 6

输出

1 2 5
2 3 13
3 4 25
4 5 41
5 6 61

分析:根据题意可知dis2=x2+y2,题目要求使用冒泡排序方法进行升序排序,算法竞赛中排序一般直接使用sort()函数。我们可以把x,y,dis2通过结构体进行操作。

Code

#include<iostream>
#include<algorithm>		//sort()函数要使用algorithm头文件
using namespace std;
typedef long long ll;	//怕dis2太大,直接开long long
struct point
{
    ll x;
    ll y;
    ll dis2;
}p[11];		//题目中n的范围是0~10,多开几个防止数组越界
bool cmp(point a,point b)
{
    return a.dis2<b.dis2;	//设置排序方式,将dis2升序排序
}
int main()
{
    int n;
    cin>>n;
    for(int i=0;i<n;i++)
    {
        cin>>p[i].x>>p[i].y;
        p[i].dis2=p[i].x*p[i].x+p[i].y*p[i].y;		//计算dis2
    }
    sort(p,p+n,cmp);		//sort()排序
    for(int i=0;i<n;i++)
    {
        cout<<p[i].x<<" "<<p[i].y<<" "<<p[i].dis2<<endl;
    }
}

shy:能看到这里并学懂,说明你们已经踏上了ACM算法竞赛之路,不过只是刚刚入门,只学了些基础语法,后续会涉及到很多算法和函数,届时更能体会到算法竞赛的乐趣(≧∇≦)ノ。

hwjw:算法竞赛不用学指针吗?

shy:算法竞赛中基本不用指针,很多指针都可以用其他的方式来代替。比如图论题可以用数组或STL的vector等来代替。

xcx:好多函数不会用怎么办啊?

shy:不用担心,比如说7.7的sort()排序,之后会新建专题进行系统化讲解。

hwjw:学完这些基础语法,遇到题还是不会做怎么办呀?

shy:算法竞赛其实是一个积累的过程,多刷题会发现很多新的知识点,每做一道题就会有一份新的收获。随着时间的沉淀,积累的知识越来越多,经验也越来越多,到时候解题自然游刃有余。

xcx、hwjw:好耶好耶!感觉现在动力满满,有点迫不及待学习新的知识了!!

  • 86
    点赞
  • 57
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
时间复杂度(渐近时间复杂度的严格定义,NP问题,时间复杂度的分析方法,主定理)   排序算法(平方排序算法的应用,Shell排序,快速排序,归并排序,时间复杂度下界,三种线性时间排  序,外部排序)   数论(整除,集合论,关系,素数,进位制,辗转相除,扩展的辗转相除,同余运算,解线性同余方程,中国剩余定理) 指针(链表,搜索判重,邻接表,开散列,二叉树的表示,多叉树的表示) 按位运算(and,or,xor,shl,shr,一些应用) 图论(图论模型的建立,平面图,欧拉公式与五色定理,求强连通分量,求割点和桥,欧拉回路,AOV问题,AOE问题,最小生成树的三种算法,最短路的三种算法,标号法,差分约束系统,验证二分图,Konig定理,匈牙利算法,KM算法,稳定婚姻系统,最大流算法,最小割最大流定理,最小费用最大流算法) 计算几何(平面解几及其应用,向量,点积及其应用,叉积及其应用,半平面相交,求点集的凸包,最近点对问题,凸多边形的交,离散化与扫描) 数据结构(广度优先搜索,验证括号匹配,表达式计算,递归的编译,Hash表,分段Hash,并查集,Tarjan算法,二叉堆,左偏树,二斜堆,二项堆,二叉查找树,红黑树,AVL平衡树,Treap,Splay,静态二叉查找树,2-d树,线段树,二维线段树,矩形树,Trie树,块状链表) 组合数学(排列与组合,鸽笼原理,容斥原理,递推,Fibonacci数列,Catalan数列,Stirling数,差分序列,生成函数,置换,Polya原理) 概率论(简单概率,条件概率,Bayes定理,期望值) 矩阵(矩阵的概念和运算,二分求解线性递推方程,多米诺骨牌棋盘覆盖方案数,高斯消元) 符串处理(KMP,后缀树,有限状态自动机,Huffman编码,简单密码学) 动态规划(单调队列,凸完全单调性,树型动规,多叉转二叉,状态压缩类动规,四边形不等式) 博奕论(Nim取子游戏,博弈树,Shannon开关游戏) 搜索(A*,ID,IDA*,随机调整,遗传算法

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HUAYI_SUN

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值