文章目录
零、常识
0.1 时空复杂度边界
-
时间:一般时间复杂度超过109,一定就超时了
-
空间:int 类型 106就超过内存了
0.2 不动态申请内存
- 尽量不用指针和动态申请内存。
- 链表用c语言实现,申请内存空间用,
#include<malloc.h>
0.3 ascll 码
空格 32
0-9 : 48-57
A-Z : 65-90
a-z : 97-122
0.4 指针
在声明变量中int* a
表示a是一个指向int类的指针
在使用变量时*a
表示的是a这个指针指向的地址存放的变量的值
0.5 头文件
#include<iostream> //C++标准输入输出,cin/cout
#include<cstdlib>
#include<cstdio> //c标准输入输出,scanf/printf
#include<algorithm> //常用算法,比如快速排序sort函数
#include<map><vector><string><set> //STL相应模块
#include<cstring> //c语言字符串相关,memset函数所在头文件
一、进位制与整数表示
1.1进制输出
printf("%d%o%x\n",a);
把整数a按照十进制、八进制和十六进制输出
如果是C++
默认状态下,数据按十进制输入输出。如果要求按八进制或十六进制输入输出,在cin或cout中必须指明相应的数据形式,oct为八进制,hex为十六进制,dec为十进制。
1 int i, j, k, l;
2 cout<<”Input i(oct), j(hex), k(hex), l(dec):”<<endl;
3 cin>>oct>>i; //输入为八进制数
4 cin>>hex>>j; //输入为十六进制数
5 cin>>k; //输入仍为十六进制数
6 cin>>dec>>l; //输入为十进制数
7 cout<<”hex:”<<”i=”<<hex<<i<<endl;
8 cout<<”dec:”<<”j=”<<dec<<j<<′\t′<<”k=”<<k<<endl;
9 cout<<”oct:”<<”l=”<<oct<<l;
10 cout<<dec<<endl; //恢复十进制输出状态
11
12 【执行结果】:
13 (1)输出提示:Input i(oct), j(hex), k(hex), l(dec):
14 (2)此时从键盘输入: 032 0x3f 0xa0 17 <CR>
15 (3)输出结果为:
16
17 hex:i=1a
18 dec:j=63 k=160
19 oct:l=21
必须在cin中指明数制,否则从键盘输入时,不认八进制和十六进制数开头的0和0x标志。指明后可省略0和0x标志。
进制控制只适用于整型变量,不适用于实型和字符型变量。
输入数据的格式、个数和类型必须与cin中的变量一一对应,否则不仅使输入数据错误,而且影响后面其他数据的正确输入。
在cin或cout中指明数制后,该数制将一直有效,直到重新指明使用其他数制。
1.2进制转换与位移
- 二进制转十进制
左移一位 = 乘以2 =<<1
eg1: (10101)2 = ((1*2+0)*2+1)*2+0)*2+1
eg2: 28-1 = (1<<8)-1
注意
移位运算符的优先级低于加减运算
1.3 int溢出
在一些题目中注意溢出的问题
二、C++字符串
做函数参数
在传递参数的时候,如果参数是string类型,可以用string类型的引用,减少内存的拷贝。
void funs(const string& str1)
{
string str;
str=str1;
...
}
这里形参用的就是引用,所以str1的地址就是实参的地址
但因为声明const,实参不能改变,所以函数内部用str做处理
基础操作
- front和back
chr1=s.front()//取第一个字符
chr2=s.back()//去最后一个字符
s.front()='a'//给第一个字符赋值
s.back()='b'//给第二个元素赋值
vector也可以用front和back取第一个最后一个元素
-
赋值:用“=”号
-
连接:用“+”号
-
长度:s.size()
-
插入子串:s.insert(插入位置,”子串”);
-
删除子串:s.erase(开始位置,长度);
-
替换子串:s.replace(开始位置,替换长度,替换成什么)
-
查找子串:s.find(要找的内容,查找起始位),
查找不到返回string::npos,找到返回起始位置
//找到subs在s中的位置,把subs从s中取出
#include<string>
string s,s0;
if(s.find(subs,0)!=string::npos)
{
n1=s.find(subs,0);
}
string r=s.substr(n1,subs.length());
- 取子串易搞错
取子串:s.substr(开始位置,长度);
如果从第0个位置开始,取到第二个位置(取到’c’)
s.substr(0,3);//而不是substr(0,2)
三、数组
3.1 声明
不确定大小的时候,数组一般会开的大一些
- 注意比较大的数组声明放在main函数外,否则程序可能无法运行
define maxn 100000
int a[maxn];
int main()
{
...
}
3.2 结构体(数组)和排序
3.2.1 定义结构体和结构体数组
struct 结构体名称{
变量类型 变量名;
};
struct 结构体名称 结构体变量名;
struct 结构体名称 结构体数组名[数组长度];
typedef struct Student{
int age;
int score;
int sno;
}Stu;
Stu stu1;
Stu stu2[30];
3.2.2 cmp重定义
如果对结构体排序,使用algorithm,需要对cmp函数重定义
bool cmp(Stu a,Stu b)
{
//先按年龄,从小到大
if(a.age<b.age) return true;
//年龄相等按成绩排,从小到大
else if(a.age==b.age && a.score<b.score) return true;
else return a.sno<b.sno;
}
3.2.3 例题
排序
#include<algorithm>
bool cmp(int a,int b)
{return a>b;}//从大到小排序
int a[N];
sort(a,a+N,cmp);//对数组a中的元素按照cmp定义的排序规则排序
定义结构体数组,初始化
先声明结构体,再去定义结构体数组
struct 结构体名{
成员列表;
};
struct 结构体名 数组名[长度] = {{成员值列表},…{成员值列表}};
字符串比较
strcmp(char *s1,char *s2)
返回值
大于0 ---------------- 第一个字符串大于第二个字符串
小于0 ---------------- 第一个字符串小于第二个字符串
等于0 ---------------- 两个字符串相等
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
typedef struct student
{
char name[100];
int age;
int grade;
}Stu;
bool cmp(Stu a,Stu b)
{
if(a.grade!=b.grade) return a.grade<b.grade;
if(strcmp(a.name,b.name)) return a.name<b.name;
return a.age<b.grade;
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
Stu stu[n];
for(int i=0;i<n;i++)
{
scanf("%s",stu[i].name);
scanf("%d",stu[i].age);
scanf("%d",stu[i].grade);
}
sort(stu,stu+n,cmp);
for(int j=0;j<n;j++)
{
printf("%s ",stu[j].name);
printf("%d ",stu[j].age);
printf("%d\n",stu[j].grade);
}
}
return 0;
}
3.3 memset初始化
memset(数组名,0/-1,sizeof(数组名))
可以直接将数组初始化为全0/全1/全-1
注意 memset只能初始化为0/-1,初始化为其他值行不通
3.4 字符数组
【读入】
scnaf("%s",s)
会读入一个不含空格、回车和TAB的字符串,存入字符数组s。
注意 不要在s前面加&
【基本操作】
#include<string.h>
char a[10],b[10];
-
strlen(s):返回s中结束标记’/0’之前的字符个数
-
strcpy(a,b):赋值
-
strcmp(a,b):比较
返回值
大于0 ---------------- 第一个字符串大于第二个字符串
小于0 ---------------- 第一个字符串小于第二个字符串
等于0 ---------------- 两个字符串相等 -
strcat(a,b):连接
3.4 数组做参数和返回值
数组做参数的时候
int sum(int a[])
等价于
int sum(int* a)
传递的只是数组的首地址
四、递归
4.1 递归
使用递归最重要的是定义递归终止条件
段溢出的原因有两种:
- 调用太多
- 局部变量过大
因为调用关系和局部变量都存放在堆栈段中
递归思想
把问题分解成规模小的两个子问题
集合的思想A=A1+A2,A1和A2是A的子集,并且是互斥的子集