
标准模板库,日常简单理解为标准库
这三个字母在C++标准文档中没有出现,是人为制造出来的东西。于是STL的概念就没那么清楚、比较模糊,比如string是标准库里的,但不是标准模板库里的。因此string是不是STL里的不好说
不用纠结定义,就当奇闻轶事乐趣
6大组件
①容器
②迭代器:理解成指针
③适配器:容器进行二次封装得到的
④算法:如sort、lower_bound
⑤仿函数:C++特性,重载了()使得具有函数功能
⑥分配器:理解为C语言的malloc、calloc
s.size(); s.length(); //返回值是 size_type,与int比较时得强转类型 //两个函数没有任何区别
错误想法:将字符串中的某一个字符改成字符串结束标志,希望把字符串给截掉
string s = "123"; s[1] = ' '; cout << s.size();
s.find("abc");
//s.find(查找什么, 下标从ind开始往后找而省略时默认为0)
//返回值也是size_type
//没找到返回值string::npos(no position 的缩写)
//没找到的返回值表现为unsigned long long的极大值即long long -1
//判断是否找到
if (s.find(...) == string::npos)
//将string::nops改成-1不太严谨
s.substr(ind, 长度) //ind指的是从下标为ind的位置开始截取 s.substr(ind); //从ind开始截取到末尾
s.replace(ind, 被替换字符串的长度, 替换成什么); //删除,替换成空字符串即可
s.insert(ind, 插入什么);
以上只是常见用法,在算法做题中够用,其它重载的功能可以在cppreference.com中查看
2. vector向量,长度不定的动态数组。头文件#include
判空v.empty(),一般不怎么用,一般用下面的
返回元素数量v.size()
在vector的最后加入元素xv.push_back(x)
清空v.clear()
以上只是写算法题时常用的,在指定位置插入元素略过,因为要使用迭代器
初始化与遍历
通过下标访问
//初始化10个int元素,默认0 vectorv1(10); //访问下标为3的元素 //访问跟数组访问的方式一样 cout << v1[3] << endl;
//初始化10个9 vectorv2(10, 9);
//二维数组 //下面的两个>分开是因为C++11标准前的编译器会把>>当成右移运算符 vector> v3(5, vector (6, 10)); //初始化5行的一维数组,每个一维数组存放6个元素10
//列表初始化、遍历 C++11特性 vectorv = {1, 2, 3, 4}; //auto自动推导类型 for (auto x : v) { cout << x << endl; }
#include#include using namespace std; int main() { vector v; int t = 0; for (int i = 0; i < 100000; i++) { v.push_back(1); if (t != v.capacity()) { t = v.capacity(); cout << t << endl; } } return 0; }
扩容规则取决于环境、编译器
下面两个操作得保证栈非空
栈是用什么实现的?stack
演示:玩一个花的。只要是类型已知,都可以存,同理也可以存储自定义类型
#include#include using namespace std; int main() { int num[10] = {1, 2, 3, 4, 5}; queue que; que.push(&num[2]); que.push(&num[4]); while (!que.empty()) { int *p = que.front(); que.pop(); cout << *p << endl; } return 0; }
自定义类型
#include#include using namespace std; struct node { int x, y; }; int main() { queue que; que.push((node){4, 6}); //que.push({4, 6}); que.push({0, 9}); que.push({5, -1}); que.push({0, 0}); cout << "元素数量:" << que.size() << endl; while (!que.empty()) { node temp = que.front(); que.pop(); cout << temp.x << " " << temp.y << endl; } return 0; }
双端队列,顺序容器,支持随机访问即可以通过[]直接访问
基本操作
判空、获得数量
插入:队尾que.push_back(x),队首que.push_front(x)
删除:队尾que.pop_back(),队首que.pop_front()
访问队首队尾元素:que.back(),que.front()
问题:以上操作时间复杂度都是常数级别O(1),随机访问不是应该内存连续?双端队列底层实现逻辑:内存不连续,二级指针,通过偏移量访问
#include7. set#include using namespace std; struct node { int x, y; //跟sort一样必须指定排序方法 //堆里面的重载逻辑反着来 bool operator<(const node &b) const { //<号,大顶堆 return this->x < b.x; } }; //方法二仿函数:重载括号的类 struct cmp { bool operator() (const node &a, const node &b) const { return a.x < b.x; } }; int main() { priority_queue que; //priority_queue , cmp> que; que.push({5, 6}); que.push({10, 1}); que.push({7, 9}); que.push({-1, 2}); que.push({6, 8}); while (!que.empty()) { node temp = que.top(); que.pop(); cout << temp.x << " " << temp.y << endl; } return 0; }
代码演示1
#include#include using namespace std; int main() { set s; s.insert(5); s.insert(8); s.insert(2); s.insert(-1); s.insert(0); cout << s.size() << endl; if (s.count(5) == 1) { cout << "5 yes" << endl; } else { cout << "5 no" << endl; } s.erase(5); if (s.count(5) == 0) { cout << "5 no" << endl; } for (auto it = s.begin(); it != s.end(); it++) { cout << (*it) << " "; } cout << endl; return 0; }
结果
代码演示2:自定义类型指定排序方法
#include#include using namespace std; struct node { int x, y; bool operator<(const node &a) const { return x + y > a.x + a.y; } }; int main() { set s; s.insert({5, 0}); s.insert({7, 2}); s.insert({4, 9}); s.insert({11, -1}); cout << s.size() << endl; for (auto it = s.begin(); it != s.end(); it++) { cout << it->x << " " << it->y << "tsum = " << it->x + it->y << endl; //it当成指针使用 } return 0; }
结果
代码演示
#include#include
结果
| #include | #include | |
|---|---|---|
| 有序去重 | set | map |
| 有序不去重 | multiset | multimap 中括号访问的是任意的,一般不用 |
| #include | #include | |
|---|---|---|
| 无序去重 | unordered_set | unordered_map |
| #include | #include | |
|---|---|---|
| 无序不去重 | unordered_multiset | unordered_multimap |
378
样例输入1
a(cc[])bbb()@
样例输出1
YES
样例输入2
a(cc[)]bbb()@
样例输出2
NO
分析:
#include2.仓库日志#include #include using namespace std; int main() { stack sta; string s; cin >> s; int f = 0; // 1不匹配 0匹配 for (auto c : s) { if (c == '(' || c == '[' || c == '{') { sta.push(c); } else if (c == ')') { if (!sta.empty() && sta.top() == '(') { sta.pop(); } else { f = 1; break; } } else if (c == ']') { if (!sta.empty() && sta.top() == '[') { sta.pop(); } else { f = 1; break; } } else if (c == '}') { if (!sta.empty() && sta.top() == '{') { sta.pop(); } else { f = 1; break; } } } if (!sta.empty()) f = 1; if (f == 1) cout << "NO" << endl; else cout << "YES" << endl; return 0; }
379
样例输入
13 0 1 0 2 2 0 4 0 2 2 1 2 1 1 2 1 2
样例输出
2 4 4 1 0
分析:建立一个辅助栈,存储最大值,每当存储的货物数量小于等于最大值栈的top元素值,则将此最大值再入一遍;若大于最大值,则入当前值。当然最开始先把0压栈。出栈时一同出栈即可(货物栈可以不需要)。
482
样例输入
dmih 11 B B P x L B B B P y D D P z
样例输出
yxz
分析:光标左右边分别建立栈
384
样例输入
4 3 6
样例输出
3
分析
575
样例输入
2 scan 10 word 15 2 scan word
样例输出
10 15
分析
569
样例输入
100 100 2 P 100 0 Z
样例输出
200 50.00000 100 100.00000
分析
struct node {
double v, c, salt;//体积、浓度、盐的质量
//salt = v * c / 100; //c的符号是%
};
7.上网统计
566
样例输入
5 7 goodstudyer bookshopa likespacea spaceweb goodstudyer bookshopb likespaceb spaceweb likespacec spaceweb likespacea juiceshop gameplayer gameweb
样例输出
goodstudyer bookshopa bookshopb likespacea spaceweb juiceshop likespaceb spaceweb likespacec spaceweb gameplayer gameweb
分析
其它题目573(用优先队列)