Acwing语法基础课C++简要整理

第1讲 C++入门及简单的顺序结构

变量的类型转换
int y = (int)x;

第2讲 printf语句与判断结构

printf输出格式
#include <cstdio>
见C

第3讲 循环结构

do while不管条件的值如何,都要至少执行一次循环

第4讲 数组

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

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;

第5讲 字符串

常用ASCII值:‘A’- 'Z’是65 ~ 90,‘a’ - 'z’是97 - 122,0 - 9是 48 - 57

gets函数在新版C++中被移除了,因为不安全。
可以用fgets代替,但注意fgets不会删除行末的回车字符

char str[100];
fgets(str, 100, stdin);

C库
#include <string.h>

可变长的字符序列,比字符数组更加好用
#include <string>

  • 初始化
    string s4(10, 'c'); // s4的内容是 "cccccccccc"
  • 不能用printf直接输出string,需要写成:
    printf(“%s”, s.c_str())
  • 使用getline读取一整行
    getline(cin, s);
  • 注意size()是无符号整数,因此s.size() <= -1一定成立
  • 当把string对象和字符字面值及字符串字面值混在一条语句中使用时,必须确保每个加法运算符的两侧的运算对象至少有一个是string
    string s5 = "hello" + ", "; // 错误:两个运算对象都不是string
    string s7 = "hello" + ", " + s2; // 错误:不能把字面值直接相加,运算是从左到右进行的

第6讲 函数

形参也可以设置默认值,但所有默认值必须是最后几个。当传入的实参个数少于形参个数时,最后没有被传入值的形参会使用默认值。

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

没有返回值的return语句只能用在返回类型是void的函数中。返回void的函数不要求非得有return语句,因为在这类函数的最后一句后面会隐式地执行return。

第7讲 类、结构体、指针、引用

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

第8讲 STL

#include <vector>

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

  • 声明
vector<int> a;      // 相当于一个长度动态变化的int数组
vector<int> b[233]; // 相当于第一维长233,第二位长度动态变化的int数组
  • clear函数把vector清空
  • 迭代器就像STL容器的“指针”,可以用星号*操作符解除引用。
    一个保存int的vector的迭代器声明方法为:
    vector<int>::iterator it;
  • begin/end
    begin函数返回指向vector中第一个元素的迭代器。例如a是一个非空的vector,则*a.begin()a[0]的作用相同。
    所有的容器都可以视作一个“前闭后开”的结构,end函数返回vector的尾部,即第n 个元素再往后的“边界”。*a.end()a[n]都是越界访问,其中n = a.size()
    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的最后一个元素。
#include <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    // 返回队尾元素
    
#include <stack>
push    // 向栈顶插入
pop     // 弹出栈顶元素
#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           // 清空队列
#include <set>

主要包括set和multiset两个容器,分别是“有序集合”和“有序多重集合”,即前者的元素不能重复,而后者可以包含若干个相等的元素。set和multiset的内部实现是一棵红黑树,它们支持的函数基本相同。

  • 声明
    set<int> s;
    struct rec{…}; set<rec> s;  // 结构体rec中必须定义小于号
    multiset<double> s;
    
  • size/empty/clear
  • 迭代器
    set和multiset的迭代器称为“双向访问迭代器”,不支持“随机访问”,支持星号*解除引用,仅支持++和–两个与算术相关的操作。
    set<int>::iterator it;
  • begin/end
    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 是被删除的元素个数。
#include <map>

map容器是一个键值对key-value的映射,其内部实现是一棵以key为关键码的红黑树。Map的key和value可以是任意类型,其中key必须定义小于号运算符

  • 声明
    map<key_type, value_type> name;
  • size/empty/clear/begin/end
  • insert/erase
    参数均是pair<key_type, value_type>
  • find
    h.find(x)在变量名为h的map中查找key为x的二元组。
  • []操作符
    h[key]返回key映射的value的引用,时间复杂度为 O(logn)
    通过h[key]来得到key对应的value,还可以对h[key]进行赋值操作,改变key对应的value。

第9讲 位运算与常用库函数

  • 位运算
符号    运算
&	与
|	或
~	非
^	异或
>>	右移
<<	左移
  • 常用操作:
    求x的第k位数字 x >> k & 1
    lowbit(x) = x & -x,返回x的最后一位1
  • 常用库函数
    • reverse翻转
      reverse(a.begin(), a.end());
      翻转一个数组,元素存放在下标1 ~ n:
      reverse(a + 1, a + n + 1);
    • unique去重
      返回去重(只去掉相邻的相同元素)之后的尾迭代器(或指针),仍然为前闭后开,即这个迭代器是去重之后末尾元素的下一个位置。
      该函数常用于离散化,利用迭代器(或指针)的减法,可计算出去重后的元素个数
      把一个vector去重:
      int m = unique(a.begin(), a.end()) – a.begin();
      把一个数组去重,元素存放在下标1 ~ n:
      int m = unique(a + 1, a + n + 1) – (a + 1);
    • random_shuffle随机打乱
      用法与reverse相同
    • sort
      对两个迭代器(或指针)指定的部分进行快速排序。可以在第三个参数传入定义大小比较的函数,或者重载“小于号”运算符。
      • 传入比较函数
        int a[MAX_SIZE];
        bool cmp(int a, int b){
            return a > b;}
        sort(a + 1, a + n + 1, cmp);
        
      • 自定义结构体,重载“小于号”运算符
        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中查找小于等于x的最大整数(假设一定存在):
      upper_bound的用法和lower_bound大致相同,唯一的区别是查找第一个大于x的元素。当然,两个迭代器(指针)指定的部分应该是提前排好序的。
      在有序int数组(元素存放在下标1 ~ n)中查找大于等于x的最小整数的下标
      int i = lower_bound(a + 1, a + 1 + n, x) - a;
      在有序vector中查找小于等于x的最大整数(假设一定存在):
      int y = *--upper_bound(a.begin(), a.end(), x);
  • 3
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

春风锤呀锤

碗在这 ,光光的T.T

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

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

打赏作者

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

抵扣说明:

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

余额充值