文章目录

  • 入门
    • 语法基础
    • 输入输出
    • 表达式
  • Printf语句与判断结构
    • printf输出格式
    • if 语句
  • 循环结构
    • while循环
    • do while循环
    • for 循环
    • 跳转语句
  • 数组
  • 字符串
    • 字符与整数的联系——ASCII码
    • 字符数组
    • 字符数组的常用操作
    • 标准库类型 string
  • 函数
    • 函数基础
    • 参数传递
  • 类、结构体、指针、引用
    • 类与结构体
    • 指针和引用
  • STL
    • vector
    • queue
    • stack
    • deque
    • set
    • map
  • 位运算与常用库函数
    • 位运算
    • 常用库函数

入门

打开编译软件,出现的第一个程序肯定是Hello Word!

#include <iostream>
using namespace std;  //C++的命名空间,可以让在不同命名空间中的函数名或变量名相同
int main()
{cout << "Hello world!" << endl;return 0;
}

语法基础

变量的定义:变量必须先定义,才可以使用。不能重名。

变量定义的方式:

#include <iostream>
using namespace std;
int main()
{int a=5;int c=a,d=10/2;return 0;
}

输入输出

整数的输入输出:

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

字符串的输入输出:

#include <iostream>
#include <string>
using namespace std;
int main()
{string str;cin>>str;cout<<str;return 0;
}

输入输出多个不同类型的变量:

#include <iostream>
#include <string>
using namespace std;
int main()
{int a,b;string str;cin>>a;cin>>b>>str;cout<<str<<" !!! "<<a+b<<endl;return 0;
}

表达式

整数的加减乘除四则运算:

#include <iostream>
#include <string>
using namespace std;
int main()
{int a=6+3*4/2-2;cout<<a<<endl;int b=a*10+5/2;cout<<b<<endl;cout<<23*56-78/3<<endl;return 0;
}


浮点数(小数)的运算:

#include <iostream>
#include <string>
using namespace std;
int main()
{float x=1.5,y=3.2;cout<<x*y<<' '<<x+y<<endl;cout<<x-y<<' '<<x/y<<endl;return 0;
}

整型变量的自增、自减:

#include <iostream>
#include <string>
using namespace std;
int main()
{int a=1;int b=a++;cout<<a<<' '<<b<<endl;int c=++a;cout<<a<<' '<<c<<endl;return 0;
}

变量的类型转换:

#include <iostream>
#include <string>
using namespace std;
int main()
{float x=123.12;int y=(int)x;cout<<x<<' '<<y<<endl;return 0;
}

Printf语句与判断结构

printf输出格式

#include <iostream>
#include <cstdio>
using namespace std;
int main()
{//注意:使用printf 时最好添加头文件 #include <cstdio>。printf("Hello World!");return 0;
}

Int、float、double、char等类型的输出格式:
(1)Int:%d
(2)Float: %f, 默认保留6位小数
(3)Double: %lf, 默认保留6位小数
(4)Char: %c, 回车也是一个字符,用’\n’表示
(5)Float, double等输出保留若干位小数时用:%.4f, %3lf

#include <iostream>
#include <cstdio>
using namespace std;
int main()
{int a=3;float b=3.12345678;double c=3.12345678;printf("%5d\n",a);
// %8.3f, 表示这个浮点数的最小宽度为8,保留3位小数,当宽度不足时在前面补空格。printf("%8.3f\n",b);
// %-8.3f,表示最小宽度为8,保留3位小数,当宽度不足时在后面补上空格printf("%-8.3f\n",b);
//%08.3f, 表示最小宽度为8,保留3位小数,当宽度不足时在前面补上0printf("%08.3f\n",b);printf("%7.3f\n",c);return 0;
}

if 语句

1.基本if-else语句,当条件成立时,执行某些语句;否则执行另一些语句。
2.Else 语句可以省略。
3.当只有一条语句时,大括号可以省略。
常用比较运算符
(1) 大于 >
(2) 小于 <
(3) 大于等于 >=
(4) 小于等于 <=
(5) 等于 ==
(6) 不等于 !=

判断闰年,闰年输出Yes,反之输出No

#include <iostream>
#include <cstdio>
using namespace std;
int main()
{int year;cin>>year;if(year%400==0 || (year%4==0 && year%100))puts("Yes");else puts("No");return 0;
}

循环结构

while循环

可以简单理解为循环版的if语句。If语句是判断一次,如果条件成立,则执行后面的语句;while是每次判断,如果成立,则执行循环体中的语句,否则停止。

求斐波那契数列的第n项。f(1)=1, f(2)=1, f(3)=2, f(n)=f(n-1) + f(n-2)。

#include <iostream>
#include <cstdio>
using namespace std;
int main()
{int n;cin>>n;int a=1,b=1,i=1;while(i<n){int c=a+b;a=b;b=c;i++;}cout<<a<<endl; return 0;
}

死循环:循环永久执行,无法结束。我们要避免写出死循环。

do while循环

do while循环不常用。
do while语句与while语句非常相似。唯一的区别是,do while语句限制性循环体后检查条件。不管条件的值如何,我们都要至少执行一次循环。

#include <iostream>
#include <cstdio>
using namespace std;
int main()
{int x=1;while(x<1){cout<<"x!"<<endl;x++;}int y=1;do{cout<<"y!"<<endl;}while(y<1);return 0;
}

for 循环

基本思想:把控制循环次数的变量从循环体中剥离。
for (init-statement : condition: expression)
{
statement
}
init-statement可以是声明语句、表达式、空语句,一般用来初始化循环变量;
condition 是条件表达式,和while中的条件表达式作用一样;可以为空,空语句表示true
expression 一般负责修改循环变量,可以为空
init-statement可以定义多个变量,expression也可以修改多个变量。

#include <iostream>
#include <cstdio>
using namespace std;
int main()
{for(int i=0;i<10;++i)cout<<i<<endl;return 0;
}

跳转语句

break可以提前从循环中退出,一般与if语句搭配。

判断一个大于1的数是否是质数。

#include <iostream>
#include <cstdio>
using namespace std;
int main()
{int n;cin>>n;bool is_prime=true;for(int i=2;i<n;i++)if(n%i==0){is_prime=false;break;}if(is_prime) cout<<"yes"<<endl;else cout<<"no"<<endl;return 0;
}

continue可以直接跳到当前循环体的结尾。作用与if语句类似。

求1~100中所有偶数的和。

#include <iostream>
#include <cstdio>
using namespace std;
int main()
{int sum=0;for(int i=1;i<=100;i++){if(i%2) continue;sum+=i;}cout<<sum<<endl;return 0;
}

打印1~100中的所有质数

#include <iostream>
#include <cstdio>
using namespace std;
int main()
{for(int i=2;i<=100;i++){bool is_prime=true;for(int j=2;j<i;j++){if(i%j==0){is_prime=false;break;}}if(is_prime) cout<<i<<endl;}return 0;
}

输入一个n,打印n阶菱形。n是奇数。

#include <iostream>
#include <cstdio>
using namespace std;
int main()
{int n;cin>>n;int cx=n/2,cy=n/2;for(int i=0;i<n;i++){for(int j=0;j<n;j++)if(abs(i-cx)+abs(j-cy)<=n/2)cout<<"*";else cout<<' ';cout<<endl;}return 0;
}

数组

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

#include <iostream>
#include <cstdio>
using namespace std;
int main()
{int a[10],b[20];float f[33];double d[123];char c[21];return 0;
}

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

#include <iostream>
#include <cstdio>
using namespace std;
int main()
{int a[3]={0,1,2};  //含有3个元素的数组,元素分别是0,1,2int b[]={0,1,1};  //维度是3的数组int c[5]={0,1,2};  //等价于 c[]={0,1,2,0,0}char d[3]={'a','b','c'};  //字符数组的初始化return 0;
}

访问数组元素,通过下标访问数组。

#include <iostream>
#include <cstdio>
using namespace std;
int main()
{int a[3]={0,1,2};  //数组下标从0开始cout<<a[0]<<' '<<a[1]<<' '<<a[2]<<endl;a[0]=5;cout<<a[0]<<endl;return 0;
}

使用数组实现求斐波那契数列的第N项。

#include <iostream>
#include <cstdio>
using namespace std;
int main()
{int n;int f[100];cin>>n;f[0]=0,f[1]=1;for(int i=2;i<=n;i++) f[i]=f[i-1]+f[i-2];cout<<f[n]<<endl;return 0;
}

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

#include <iostream>
#include <algorithm>
using namespace std;
int main()
{int n,k;int a[100];cin>>n>>k;for(int i=0;i<n;i++) cin>>a[i];reverse(a,a+k);reverse(a+k,a+n);reverse(a,a+n);for(int i=0;i<n;i++) cout<<a[i]<<' ';cout<<endl;return 0;
}

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

#include <iostream>
#include <algorithm>
using namespace std;
int main()
{int a[10000],size=1,n;a[0]=1;cin>>n;while(n--){int t=0;for(int i=0;i<size;i++){t+=a[i]*2;a[i]=t%10;t/=10;}if(t) a[size++]=t;}for(int i=size-1;~i;i--) cout<<a[i];cout<<endl;return 0;
}

多维数组:多维数组就是数组的数组。
Int a[3][4]; // 大小为3的数组,每个元素是含有4个整数的数组。
Int arr[10][20][30] = {0}; /*** 将所有元素初始化为0
,大小为10的数组,它的每个元素是含有4个整数的数组, 这些数组的元素是含有30个整数的数组 ***/

#include <iostream>
#include <algorithm>
using namespace std;
int main()
{int b[3][4]={   //三个元素,每个元素是大小为4的数组{0,1,2,3},   //第一行的初始值{4,5,6,7},   //第二行的初始值{8,9,10,11}  //第三行的初始值};return 0;
}

输入一个n行m列的矩阵,从左上角开始将其按回字形的顺序顺时针打印出来。

#include <iostream>
#include <algorithm>
using namespace std;
int main()
{int n,m;int arr[50][50];cin>>n>>m;for(int i=0;i<n;i++)for(int j=0;j<m;j++) cin>>arr[i][j];bool st[50][50]={false};int dx[4]={-1,0,1,0},dy[4]={0,1,0,-1};int d=1,x=0,y=0;for(int i=0;i<n*m;i++){int a=x+dx[d],b=y+dy[d];if(a<0 || a>=n || b<0 || b>=m || st[a][b]){d=(d+1)%4;a=x+dx[d],b=y+dy[d];}cout<<arr[x][y]<<' ';//   cout<<"x = "<<x<<' '<<"y = "<<y<<endl;st[x][y]=true;x=a,y=b;}cout<<endl;return 0;
}

字符串

字符与整数的联系——ASCII码

每个常用字符都对应一个-128~127的数字,二者之间可以相互转化

#include <iostream>
using namespace std;
int main()
{char c='a';cout<<(int)c<<endl;int a=66;cout<<(char)a<<endl;return 0;
}

常用ASCII值:’A’-‘Z’ 是65~90,’a’-‘z’是97-122,’0’-‘9’是48-57。字符可以参与运算,运算时会将其当做整数

#include <iostream>
using namespace std;
int main()
{int a='B'-'A';int b='A'*'B';char c='A'+2;cout<<a<<endl;cout<<b<<endl;cout<<c<<endl;return 0;
}

输入一行字符,统计出其中数字字符的个数,以及字母字符的个数。

#include <iostream>
using namespace std;
int main()
{int n=0,c=0;string s;cin>>s;for(int i=0;i<s.size();i++){if(s[i]>='0'&&s[i]<='9') n++;if((s[i]>='a'&&s[i]<='z')||(s[i]>='A'&&s[i]<='Z')) c++;}cout<<n<<' '<<c<<endl;return 0;
}

字符数组

字符串就是字符数组加上结束符’\0’。可以使用字符串来初始化字符数组,但此时要注意,每个字符串结尾会暗含一个’\0’字符,因此字符数组的长度至少要比字符串的长度多1!

#include <iostream>
using namespace std;
int main()
{char a1[]={'C','+','+'};   //列表初始化,没有空字符char a2[]={'C','+','+','\0'};  //列表初始化,含有显示的空字符 char a3[]="C++";  //自动添加表示字符串结尾的空字符char a4[6]="Daniel";  //错误:没有空间可存放空字符!return 0;
}

字符数组的输入输出

#include <iostream>
using namespace std;
int main()
{char str[100];cin>>str;   //输入字符串时,遇到空格或者回车就会停止!cout<<str<<endl;  //输出字符串时,遇到空格或者回车不会停止printf("%s\n",str);return 0;
}

读入一行字符串,包括空格

#include <iostream>
using namespace std;
int main()
{char str[100];gets(str);cout<<str<<endl;return 0;
}

字符数组的常用操作

下面几个函数需要引入头文件: #include <string.h>
(1)strlen(str):求字符串的长度
(2)strcmp(a, b):比较两个字符串的大小,a < b 返回-1,a == b 返回0,a > b返回1。这里的比较方式是字典序!
(3)strcpy(a, b):将字符串b复制给从a开始的字符数组。

#include <iostream>
#include <string.h>
using namespace std;
int main()
{char a[100]="hello world!",b[100];cout<<strlen(a)<<endl;strcpy(b,a);cout<<strcmp(a,b)<<endl;return 0;
}

遍历字符数组中的字符

#include <iostream>
#include <string.h>
using namespace std;
int main()
{char a[100]="hello world!";for(int i=0;i<strlen(a);i++) cout<<a[i]<<endl;return 0;
}

标准库类型 string

可变长的字符序列,比字符数组更加好用。需要引头文
件:#include <string>

定义和初始化

#include <iostream>
#include <string>
using namespace std;
int main()
{string s1;   //默认初始化,s1是一个空字符串string s2=s1;  //s2是s1的副本string s3="hiya";  //s3是该字符串字面值的副本string s4(10,'c');  //s4的内容是 ccccccccccreturn 0;
}

string的读写

#include <iostream>
#include <string>
using namespace std;
int main()
{string s1,s2;cin>>s1>>s2;cout<<s1<<s2<<endl;return 0;
}

不能用printf直接输出string,需要写成:printf(“%s”, s.c_str())
使用getline读取一整行

#include <iostream>
#include <string>
using namespace std;
int main()
{string s;getline(cin,s);cout<<s<<endl;return 0;
}

string的empty和size操作(注意size是无符号整数,因此 s.size() <= -1一定成立)

#include <iostream>
#include <string>
using namespace std;
int main()
{string s1,s2="abc";cout<<s1.empty()<<endl;cout<<s2.empty()<<endl;cout<<s2.size()<<endl;return 0;
}

string 的比较:支持 > < >= <= == !=等所有比较操作,按字典序进行比较。
为string对象赋值:
string s1(10, ‘c’), s2; // s1的内容是 cccccccccc;
//s2是一个空字符串
s1 = s2; // 赋值:用s2的副本替换s1的副本
// 此时s1和s2都是空字符串
两个string对象相加:
string s1 = “hello, ”, s2 = “world\n”;
string s3 = s1 + s2; // s3的内容是 hello, world\n
s1 += s2; // s1 = s1 + s2
字面值和string对象相加:做加法运算时,字面值和字符都会被转化成string对象,因此直接相加就是将这些字面值串联起来:
string s1 = “hello”, s2 = “world”; // 在s1和s2中都没有标点符号
string s3 = s1 + “, “ + s2 + ‘\n’;
当把string对象和字符字面值及字符串字面值混在一条语句中使用时,必须确保每个加法运算符的两侧的运算对象至少有一个是string:
string s4 = s1 + “, “; // 正确:把一个string对象和有一个字面值相加
string s5 = “hello” +”, “; // 错误:两个运算对象都不是string
string s6 = s1 + “, “ + “world”; // 正确,每个加法运算都有一个运算符是string
string s7 = “hello” + “, “ + s2; // 错误:不能把字面值直接相加,运算是从左到右进行的。

处理string对象中的字符,可以将string对象当成字符数组来处理

#include <iostream>
#include <string>
using namespace std;
int main()
{string s="hello word";for(int i=0;i<s.size();i++) cout<<s[i]<<endl;return 0;
}

使用基于范围的for语句

#include <iostream>
#include <string>
using namespace std;
int main()
{string s="hello word";for(char c : s) cout<<c<<endl;for(char &c : s) c='a';cout<<s<<endl;return 0;
}

函数

函数基础

一个典型的函数定义包括以下部分:返回类型、函数名字、由0个或多个形参组成的列表以及函数体。

int fact(int val)  //求阶乘的程序
{int ret = 1;while (val > 1)ret *= val -- ;return ret;
}

函数名字是fact,它作用于一个整型参数,返回一个整型值。return语句负责结束fact并返回ret的值。
调用函数

int main()
{int j = fact(5);cout << "5! is " << j << endl;return 0;
}

函数的调用完成两项工作:一是用实参初始化函数对应的形参,二是将控制权转移给被调用函数。此时,主调函数的执行被暂时中断,被调函数开始执行。
形参和实参

实参是形参的初始值。第一个实参初始化第一个形参,第二个实参初始化第二个形参,依次类推。形参和实参的类型和个数必须匹配。
fact(“hello”); // 错误:实参类型不正确
fact(); // 错误:实参数量不足
fact(42, 10, 0); // 错误:实参数量过多
fact(3.14); // 正确:该实参能转换成int类型,等价于fact(3);
形参也可以设置默认值,但所有默认值必须是最后几个。当传入的实参个数少于形参个数时,最后没有被传入值的形参会使用默认值。

函数的形参列表

函数的形参列表可以为空,但是不能省略。
void f1() {/* …. /} // 隐式地定义空形参列表
void f2(void) {/
/} // 显式地定义空形参列表
形参列表中的形参通常用逗号隔开,其中每个形参都是含有一个声明符的声明。即使两个形参的类型一样,也必须把两个类型都写出来:
int f3(int v1, v2) {/
/} // 错误
int f4(int v1, int v2) {/
… */} // 正确

函数返回类型

大多数类型都能用作函数的返回类型。一种特殊的返回类型是void,它表示函数不返回任何值。函数的返回类型不能是数组类型或函数类型,但可以是指向数组或者函数的指针。

局部变量、全局变量与静态变量

局部变量只可以在函数内部使用,全局变量可以在所有函数内使用。当局部变量与全局变量重名时,会优先使用局部变量。

参数传递

传值参数:当初始化一个非引用类型的变量时,初始值被拷贝给变量。此时,对变量的改动不会影响初始值。

#include <iostream>
#include <string>
using namespace std;
int f(int x)
{x=5;
}
int main()
{int x=10;f(x);cout<<x<<endl;return 0;
}

传引用参数:当函数的形参为引用类型时,对形参的修改会影响实参的值。使用引用的作用:避免拷贝、让函数返回额外信息。

#include <iostream>
#include <string>
using namespace std;
int f(int &x)
{x=5;
}
int main()
{int x=10;f(x);cout<<x<<endl;return 0;
}

数组形参:在函数中对数组中的值的修改,会影响函数外面的数组。
一维数组形参的写法:
// 尽管形式不同,但这三个print函数是等价的
void print(int a) {//}
void print(int a[]) {/
/}
void print(int a[10]) {/
… */}

#include <iostream>
#include <string>
using namespace std;
int print(int a[])
{for(int i=0;i<10;i++) cout<<a[i]<<endl;
}
int main()
{int a[10];for(int i=0;i<10;i++) a[i]=i;print(a);return 0;
}

多维数组形参的写法:多维数组中,除了第一维之外,其余维度的大小必须指定
void print(int (a)[10]) {//}
void print(int a[][10]) {/
… */}

#include <iostream>
#include <string>
using namespace std;
int print(int a[][10])
{for(int i=0;i<10;i++){for(int j=0;j<10;j++)cout<<a[i][j]<<' ';cout<<endl;}
}
int main()
{int a[10][10];for(int i=0;i<10;i++)for(int j=0;j<10;j++)a[i][j]=j;print(a);return 0;
}

返回类型和return语句:return 语句终止当前正在执行的函数并将控制权返回到调用该函数的地方。return语句有两种形式:
return;
return expression;

无返回值函数:没有返回值的return语句只能用在返回类型是void的函数中。返回void的函数不要求非得有return语句,因为在这类函数的最后一句后面会隐式地执行return。通常情况下,void函数如果想在它的中间位置提前退出,可以使用return语句。return的这种用法有点类似于我们用break语句退出循环。

void swap(int &v1,int &v2)
{// 如果两个值相等,则不需要交换,直接退出if (v1 == v2)return;// 如果程序执行到了这里,说明还需要继续完成某些功能int tmp = v2;v2 = v1;v1 = tmp;// 此处无须显示的return语句
}

有返回值的函数:只要函数的返回类型不是void,则该函数内的每条return语句必须返回一个值。return语句返回值的类型必须与函数的返回类型相同,或者能隐式地转换函数的返回类型。

#include <iostream>
using namespace std;
int max(int x,int y)
{if(x>y) return x;return y;
}
int main()
{int x,y;cin>>x>>y;cout<<max(x,y)<<endl;return 0;
}

函数递归:在一个函数内部,也可以调用函数本身。

#include <iostream>
using namespace std;
int fact(int n)
{if(n<=1) return 1;return n*fact(n-1);
}
int main()
{int n;cin>>n;cout<<fact(n)<<endl;return 0;
}

类、结构体、指针、引用

类与结构体

类的定义:类中的变量和函数被统一称为类的成员变量。
private后面的内容是私有成员变量,在类的外部不能访问;public后面的内容是公有成员变量,在类的外部可以访问。

#include <iostream>
using namespace std;
const int N = 1000010;
class Person
{private:int age, height;double money;string books[100];public:string name;void say(){cout << "I'm " << name << endl;}int set_age(int a){age = a;}int get_age(){return age;}void add_money(double x){money += x;}
} person_a, person_b, persons[100];int main()
{Person c;c.name = "Edviv";      // 正确!访问公有变量c.age = 18;          // 错误!访问私有变量c.set_age(18);       // 正确!set_age()是共有成员变量c.add_money(100);c.say();cout << c.get_age() << endl;return 0;
}

结构体和类的作用是一样的。不同点在于类默认是private,结构体默认是public。

指针和引用

指针指向存放变量的值的地址。因此我们可以通过指针来修改变量的值

#include <iostream>
using  namespace std;
int main()
{int a=10;int *p=&a;*p+=5;cout<<*p<<endl;return 0;
}

数组名是一种特殊的指针,指针可以做运算

#include <iostream>
using  namespace std;
int main()
{int a[5]={1,2,3,4,5};for(int i=0;i<5;i++) cout<<*(a+i)<<endl;return 0;
}

引用和指针类似,相当于给变量起了个别名

#include <iostream>
using  namespace std;
int main()
{int a=10;int &p=a;p+=5;cout<<p<<endl;return 0;
}

单链表

#include <iostream>
#include <string.h>
using  namespace std;
const int N=10000;
struct Node
{int val;Node *next;
}*head;
int main()
{for(int i=1;i<=5;i++){Node *p=new Node();p->val=i;p->next=head;head=p;}for(Node *p=head;p;p=p->next) cout<<p->val<<' ';cout<<endl;return 0;
}

STL

vector

vector是变长数组,支持随机访问,不支持在任意位置 O(1)O(1)O(1) 插入。为了保证效率,元素的增删一般应该在末尾进行。

声明:#include <vector>   头文件vector<int> a;     相当于一个长度动态变化的int数组vector<int> b[233];  相当于第一维长233,第二位长度动态变化的int数组struct rec{…};vector<rec> c;     自定义的结构体类型也可以保存在vector中

size/empty

size函数返回vector的实际长度(包含的元素个数),empty函数返回一个bool类型,表明vector是否为空。二者的时间复杂度都是O(1)O(1)O(1)。
所有的STL容器都支持这两个方法,含义也相同,之后我们就不再重复给出。

clear

clear函数把vector清空。

迭代器

迭代器就像STL容器的“指针”,可以用星号“*”操作符解除引用。一个保存int的
vector的迭代器声明方法:vector<int>::iterator it;vector的迭代器是“随机
访问迭代器”,可以把vector的迭代器与一个整数相加减,其行为和指针的移动类
似。可以把vector的两个迭代器相减,其结果也和指针相减类似,得到两个迭代器
对应下标之间的距离。

begin/end

begin函数返回指向vector中第一个元素的迭代器。例如a是一个非空的vector,则
*a.begin()与a[0]的作用相同。
所有的容器都可以视作一个“前闭后开”的结构,end函数返回vector的尾部,即第n
个元素再往后的“边界”。*a.end()与a[n]都是越界访问,其中n=a.size()。
下面两份代码都遍历了vector<int>a,并输出它的所有元素。
for (int I = 0; I < a.size(); I ++) cout << a[i] << endl;for (vector<int>::iterator it = a.begin(); it != a.end(); it ++) cout << *it << endl;

front/back

front函数返回vector的第一个元素,等价于*a.begin() 和 a[0]。
back函数返回vector的最后一个元素,等价于*==a.end() 和 a[a.size() – 1]。

push_back() 和 pop_back()

a.push_back(x) 把元素x插入到vector a的尾部。
b.pop_back() 删除vector a的最后一个元素。

queue

#include <queue>头文件queue主要包括循环队列queue和优先队列
priority_queue两个容器。
声明:queue<int> q;struct rec{…}; queue<rec> q;     //结构体rec中必须定义小于号priority_queue<int> q;        // 大根堆priority_queue<int, vector<int>, greater<int> q;   // 小根堆priority_queue<pair<int, int>>q;

循环队列 queue

push 从队尾插入
pop 从队头弹出
front 返回队头元素
back 返回队尾元素

优先队列 priority_queue

push 把元素插入堆
pop 删除堆顶元素
top     查询堆顶元素(最大值)

stack

#include <stack>
头文件stack包含栈。声明和前面的容器类似。
push 向栈顶插入
pop 弹出栈顶元素

deque

#include <deque>
双端队列deque是一个支持在两端高效插入或删除元素的连续线性存储空间。它就像
是vector和queue的结合。与vector相比,deque在头部增删元素仅需要O(1)的时间;
与queue相比,deque像数组一样支持随机访问。
[] 随机访问
begin/end,返回deque的头/尾迭代器
front/back 队头/队尾元素
push_back 从队尾入队
push_front 从队头入队
pop_back 从队尾出队
pop_front 从队头出队
clear 清空队列

set

#include <set>
头文件set主要包括set和multiset两个容器,分别是“有序集合”和“有序多重集合”,
即前者的元素不能重复,而后者可以包含若干个相等的元素。set和multiset的内部
实现是一棵红黑树,它们支持的函数基本相同。
声明:set<int> s;struct rec{…}; set<rec> s; // 结构体rec中必须定义小于号multiset<double> s;size/empty/clear与vector类似

迭代器

set和multiset的迭代器称为“双向访问迭代器”,不支持“随机访问”,支持星号(*)
解除引用,仅支持”++”和--“两个与算术相关的操作。
设it是一个迭代器,例如set<int>::iterator it;
若把it++,则it会指向“下一个”元素。这里的“下一个”元素是指在元素从小到大排
序的结果中,排在it下一名的元素。同理,若把it--,则it将会指向排在“上一个”
的元素。

begin/end

返回集合的首、尾迭代器,时间复杂度均为O(1)。
s.begin() 是指向集合中最小元素的迭代器。
s.end() 是指向集合中最大元素的下一个位置的迭代器。
换言之,就像vector一样,是一个“前闭后开”的形式。
因此--s.end()是指向集合中最大元素的迭代器。

insert

s.insert(x)把一个元素x插入到集合s中,时间复杂度
为 O(logn)。
在set中,若元素已存在,则不会重复插入该元素,对集
合的状态无影响。

find

s.find(x) 在集合s中查找等于x的元素,并返回指向该
元素的迭代器。若不存在,则返回s.end()。时间复杂
度为 O(logn)。

lower_bound/upper_bound

这两个函数的用法与find类似,但查找的条件略有不同,
时间复杂度为 O(logn)。
s.lower_bound(x) 查找大于等于x的元素中最小的一个,
并返回指向该元素的迭代器。
s.upper_bound(x) 查找大于x的元素中最小的一个,并
返回指向该元素的迭代器。

erase

设it是一个迭代器,s.erase(it) 从s中删除迭代器it
指向的元素,时间复杂度为O(logn)
设x是一个元素,s.erase(x) 从s中删除所有等于x的元
素,时间复杂度为O(k+logn),其中k是被删除的元素个
数。

count

s.count(x) 返回集合s中等于x的元素个数,时间复杂
度为 O(k +logn),其中k为元素x的个数。

map

#include <map>
map容器是一个键值对key-value的映射,其内部实现是
一棵以key为关键码的红黑树。Map的key和value可以是
任意类型,其中key必须定义小于号运算符。
声明:map<key_type, value_type> name;例如:map<long, long, bool> vis;map<string, int> hash;map<pair<int, int>, vector<int>> test;size/empty/clear/begin/end均与set类似。Insert/erase与set类似,但其参数均是pair<key_type, value_type>。

find

h.find(x) 在变量名为h的map中查找key为x的二元组。

[]操作符:

h[key] 返回key映射的value的引用,时间复杂度为
O(logn)。
[]操作符是map最吸引人的地方。我们可以很方便地通过
h[key]来得到key对应的value,还可以对h[key]进行赋值
操作,改变key对应的value。

位运算与常用库函数

位运算

& 与
| 或
~ 非
^ 异或
>> 右移
<< 左移常用操作:
(1)求x的第k位数字  x >> k & 1
(2)lowbit(x) = x & -x,返回x的最后一位1

常用库函数

reverse 翻转

翻转一个vector:reverse(a.begin(), a.end());
翻转一个数组,元素存放在下标1~n:
reverse(a + 1, a + 1 + n);

unique 去重

返回去重之后的尾迭代器(或指针),仍然为前闭后开,
即这个迭代器是去重之后末尾元素的下一个位置。该函
数常用于离散化,利用迭代器(或指针)的减法,可计
算出去重后的元素个数。
把一个vector去重:
int m =unique(a.begin(), a.end()) – a.begin();
把一个数组去重,元素存放在下标1~n:
int m = unique(a + 1, a + 1 + n) – (a + 1);

random_shuffle 随机打乱

用法与reverse相同

sort

对两个迭代器(或指针)指定的部分进行快速排序。可
以在第三个参数传入定义大小比较的函数,或者重载“小
于号”运算符。
把一个int数组(元素存放在下标1~n)从大到小排序,
传入比较函数:
int a[MAX_SIZE];
bool cmp(int a, int b) {return a > b; }
sort(a + 1, a + 1 + n, cmp);
把自定义的结构体vector排序,重载“小于号”运算符:
struct rec{ int id, x, y; }
vector<rec> a;
bool operator <(const rec &a, const rec &b) {return a.x < b.x || a.x == b.x && a.y < b.y;
}
sort(a.begin(), a.end());

lower_bound/upper_bound 二分

lower_bound 的第三个参数传入一个元素x,在两个迭
代器(指针)指定的部分上执行二分查找,返回指向第
一个大于等于x的元素的位置的迭代器(指针)
upper_bound 的用法和lower_bound大致相同,唯一的
区别是查找第一个大于x的元素。当然,两个迭代器(
指针)指定的部分应该是提前排好序的。
在有序int数组(元素存放在下标1~n)中查找大于等于
x的最小整数的下标:
int I = lower_bound(a + 1, a + 1 + n,. x) – a;
在有序vector<int> 中查找小于等于x的最大整数(假
设一定存在):
int y = *--upper_bound(a.begin(), a.end(), x);

Cpp 语法基础总结相关推荐

  1. Java基础笔记(入门,语法基础,流程控制,数组)

    Java语言入门 发展历程 三大技术体系 JavaSE 标准版 JavaEE 企业版 JavaME 嵌入式版 Java语言特点 简单性 健壮性 面向对象 分布式 多线程 动态性 可移植性(跨平台) J ...

  2. 给Java初学者福利——Java语法基础

    Java代码基本格式 Java中所有程序代码都必须存在于一个类中,用class关键字定义类,在class之前可以有一些修饰符.格式如下: 修饰符 class 类名 { 程序代码 } 注: 1.Java ...

  3. python语法基础知识总结-python语法基础知识

    一.数字类型及操作 1.整数类型 可正可负,无取值范围限制pow(x,y):计算x^y 2.浮点数类型 存在不确定尾数round(x,d):对x四舍五入,d为小数截取位数e/E:a*10^b 3.复数 ...

  4. VRML语法基础跟简介

    VRML语法基础和简介 VRML简介和基础语法 -------------------------------------------- 一.VRML是什么 VRML是虚拟现实造型语言 (Virtua ...

  5. Web开发(一)·期末不挂之第四章·CSS语法基础(CSS选择器选择器优先级各类样式表的使用方法)

    CSS语法基础 一.单纯html控制样式的缺点 二. CSS✪✪✪ CSS概述 CSS基础语法 组成 选择器 标签选择器 类选择器 id选择器 通配选择器 后代选择器 插入样式表的三种方式 行内样式 ...

  6. [Python从零到壹] 三.语法基础之文件操作、CSV文件读写及面向对象

    欢迎大家来到"Python从零到壹",在这里我将分享约200篇Python系列文章,带大家一起去学习和玩耍,看看Python这个有趣的世界.所有文章都将结合案例.代码和作者的经验讲 ...

  7. java的基础语法是什么_java语法基础

    java语法基础 引导语:作为一门计算机语言,Java也是有语法的,以下是百分网小编分享给大家的java语法基础,欢迎阅读! java语法基础: 1,关键字:其实就是某种语言赋予了特殊含义的单词. 保 ...

  8. HDLBits答案(1)_Verilog语法基础

    HDLBits_Verilog语法基础 线信号 与物理电线不同,Verilog中的线信号(和其他信号)是"方向性的".这意味着信息只向一个方向流动,从驱动程序流向接收器.在Veri ...

  9. java的封装性_Java10-java语法基础(九)——java的封装性

    Java10-java语法基础(九)--java的封装性 一.Java的三大特性:封装.多态.继承 封装:通过类封装对象的数据成员和成员方法,保证只有可信的类或者对象能够访问这些方法和数据成员,对不可 ...

  10. python创建和控制的实体称为_Python语法基础

    Python语法基础 数据对象和组织 对现实世界实体和概念的抽象 简单类型(表示):整数-int.浮点数-float.复数-complex.逻辑值-bool.字符串-str 容器类型(组织):列表-l ...

最新文章

  1. 如何重装计算机操作系统,自己如何重装笔记本电脑操作系统呢?
  2. CVPR 2021| 端到端场景无关视觉定位算法(SuperGlue一作出品)
  3. 一例IBM服务器Raid磁盘阵列故障
  4. Java Excel 插入图片
  5. Redis源码剖析(八)链表
  6. weblogic 扫描不到jar包的类问题解决方案
  7. myeclipse 运行速度慢的解决方案
  8. JAVA入门级教学之(逻辑(布尔)运算符)
  9. httpd Server not started: (13)Permission denied: make_sock: could not bind to address [::]:88
  10. Mvn : Maven的依赖管理 依赖冲突 解决思路
  11. devops开发运维一体化_进阶 | 中国电信系统集成公司:100% 应用 DevOps 理念,做好企业级行业应用...
  12. 物联网项目设计(一) 需求分析与概要设计
  13. 米家1代电动牙刷 更换电池
  14. 全量发布与灰度发布(APP版本发布)
  15. 如何将一个压缩包在不解压的情况下,进行分卷
  16. 【bzoj3698】XWW的难题 有上下界最大流
  17. 用开源代码如何建立网站_建立更可插拔的开源文化
  18. php获取下周时间,从PHP获取下周的日期
  19. MOS管和电机驱动(一):MOS管的栅极电阻和GS电阻 米勒效应与米勒平台
  20. 计算机主机启动不了系统安装,台式机无法开机怎么重装win7系统

热门文章

  1. Linux -shell 基础
  2. java打印指定宽度_如何设置图片打印尺寸,长与宽指定大小(CM)?
  3. 计算机类的竞赛一般多会报,2017自主招生报考条件建议65问,涵盖所有问题!...
  4. 水果店营业额下降原因,水果店如何提高营业额
  5. 目标检测:损失函数之SmoothL1Loss
  6. matlab列主元消去法求逆矩阵,Gauss-Jordan列主元消元法求逆矩阵
  7. python重启电脑
  8. 百度收录批量查询-免费百度整站批量收录查询工具
  9. 动态显示姓名--汇编语言版
  10. 学习随笔——2.仿苹果官网效果,滚动缩放图片