C++ STL详解
Posted C和C加加
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++ STL详解相关的知识,希望对你有一定的参考价值。
来源:blog.csdn.net/qq_41575507/article/details/113894814
刷题时常用的STL
string
之前写过一篇 string 的简介但是不是特别全面,这里再补充说明一下。
size()
返回字符串中字符的数量
using namespace std;
int main() {
string str = "AC-fun";
cout << str.size();
// 输出结果:6
return 0;
}
clear()
清空一个字符串
using namespace std;
int main() {
string s = "string";
cout << s;
s.clear(); // 清空一个字符串
cout << endl;
cout << "清空后字符串的长度为:" << s.size() << endl;
cout << "清空后字符串的内容为:" << s;
return 0;
}
操作符(Operators)
你可以用 ==, >, <, >=, <=, !=
比较字符串,可以用 +
或者 +=
操作符连接两个字符串,并且可以用 []
获取特定的字符。
compare()
compare() 函数以多种方式比较本字符串和 str,按照 字典序 进行排序。使用 this 代表当前字符串,str 代表与 this 比较的字符串。那么如果“ this > str” 则 返回值大于零;如果“this = str ” 那么 返回值等于零;如果 “this < str ”那么 返回值小于零。此函数也有多种比较方式,下面分别进行介绍。
比较自己 (this) 和 str
using namespace std;
int main() {
string str1 = "aaa", str2 = "ab";
if (str1.compare(str2) > 0) cout << "str1 > str2";
else if (str1.compare(str2) == 0) cout << "str1 = str2";
else cout << "str1 < str2";
// 输出结果:str1 < str2
return 0;
}
比较 自己的子串 和 str
子串以 index 索引开始(从 0 开始),长度为 length。形式为:str1.compare(index, length, str2)
表示比较 str1 的子串与 str2 的大小。
using namespace std;
int main() {
string str1 = "abcdef", str2 = "ef";
int flag = str1.compare(4, 2, str2);
if (flag) cout << "str1 > str2";
else if (flag == 0) cout << "str1 = str2";
else cout << "str1 < str2";
// 输出结果:str1 = str2
return 0;
}
•比较 自己的子串 和 str的子串
比较形式为:str1.compare(index, length, str2, index2, length2)。其中 index2 和 length2 引用 str,index 和 length 引用str1。如果不写 index2 则 str2 的子串以索引 0 开始,长度为 length2,str1 的子串以 index 开始,长度为 length。
using namespace std;
int main() {
string str1 = "abcdef", str2 = "abef";
int flag = str1.compare(4, 2, str2, 2, 2);
if (flag) cout << "str1 > str2";
else if (flag == 0) cout << "str1 = str2";
else cout << "str1 < str2";
// 输出结果:str1 = str2
return 0;
}
substr()
substr()返回本字符串的一个子串,从index开始,长num个字符。形式为:str.substr(index, length)
。如果不写参数 length 或者参数 length 超过了 str 的长度,那么就将从 index 开始之后的所有字符输出。
using namespace std;
int main() {
string str = "AC-fun";
cout << str.substr(3, 3);
// 输出结果:fun
return 0;
}
c_str()
using namespace std;
int main() {
string str = "AC-fun";
printf("%s", str.c_str());
// 输出结果:AC-fun
return 0;
}
find()
在字符串中查找字符串。此函数有三种重载方式。下面分别进行介绍。
str1.find(string str2, int index)
返回 str2 在字符串 str1 中第一次出现的位置(从index开始查找)如果不写 index 参数,则直接从 str1 的开头开始查找。如果找到了返回 **str2 ** 第一次出现的位置(下标从 0 开始);如果没找到则返回 string::npos。对于 string::npos C++ 的官方文档对它的解释为:
static const size_t npos = -1; npos是一个静态成员常量值,对于 size_t 类型的元素,该常量的最大值可能。该值在字符串成员函数中用作len(或sublen)参数的值时,表示“直到字符串结尾”。作为返回值,通常用于表示没有匹配项。该常量定义为值 -1,这是因为 size_t 是无符号整数类型,因此它是此类型可能的最大可表示值。
因此,在判断字符串有没有时,可以直接判断是否等于 string::npos
,也可以判断是否等于 -1
。
using namespace std;
int main() {
string str1 = "AC-fun", str2 = "fun", str3 = "good";
if (str1.find(str2, 0) != -1) cout << "Yes" << endl;
if (str1.find(str3, 0) == string::npos) cout << "No";
// 输出结果:Yes
// No
return 0;
}
str1.find(char ch, int index)
返回字符 ch 在字符串中第一次出现的位置(从 index 开始查找)。如果没找到就返回string::npos
。
using namespace std;
int main() {
string str1 = "AC-fun";
if (str1.find('-', 0) != -1) puts("Yes");
else puts("No");
// 输出结果:Yes
return 0;
}
关于string的更多用法
string还有很多函数,但是一般常用的函数就是以上提到的,想要学习更多用法请看:C++ API string
priority_queue
priority_queue 优先队列总能 保证优先级最高的元素位于队头,最重要的原因是其底层采用 堆 数据结构存储结构。STL 的优先队列默认是 大根堆,即最大的元素总是位于队头。其操作方式与队列 queue 基本相同。优先队列的头文件也是 #include<queue>。时间复杂度为:O(nl o g n lognlogn)。
push()
插入元素,并对底层容器排序。
using namespace std;
int main() {
priority_queue<int> heap;
heap.push(1);
heap.push(2);
heap.push(3);
// 使用 top() 访问堆顶元素
cout << heap.top();
// 输出结果:3
return 0;
}
top()
访问堆顶元素。演示代码同 push()。
empty()
检查底层的容器是否为空。若底层容器为空则为 true
,否则为 false
。
size()
返回底层容器中的元素个数,即 heap.size()。
using namespace std;
int main() {
priority_queue<int> heap;
heap.push(1);
heap.push(2);
heap.push(3);
cout << heap.size();
// 输出结果:3
return 0;
}
pop()
弹出堆顶元素。
using namespace std;
int main() {
priority_queue<int> heap;
heap.push(1);
heap.push(2);
heap.push(3);
cout << "当前堆顶元素为:" << heap.top() << endl;
// 弹出堆顶元素
heap.pop();
cout << "当前堆顶元素为:" << heap.top();
return 0;
}
如何定义小根堆
第一种方式是可以直接插入 -x,那么就可以直接利用大根堆创建了小根堆,输出的时候输出 -x 即可。
第二种方式是使用 priority_queue 提供的方法。
using namespace std;
int main() {
// 定义一个小根堆
priority_queue<int, vector<int>, greater<int> > heap;
heap.push(1);
heap.push(2);
heap.push(3);
cout << "当前堆顶元素为:" << heap.top() << endl;
return 0;
}
堆排序
堆是一棵 完全二叉树 ,可以使用数组模拟堆的实现。可以使用一维数组 h[] 来进行存储,对于根节点 x ,它的左儿子的下标为 x ∗ *∗ 2,右儿子的下标为 x ∗ *∗ 2 + 1。
构建一个小跟堆其中最关键的一个函数就是 down() 函数。只要当前的根节点不是最小的元素那么就将其向下移动。直到当前的根节点是最小的元素。代码及主要思路如下:
void down(int u) {
int t = u;
// 找出根、左、右三个点做小的那个点
if (2 * u <= cnt && h[2 * u] < h[t]) t = 2 * u;
// 首先判断一下当前的根节点有没有左孩子,如果有判断一下根节点和左孩子的大小
if (2 * u + 1 <= cnt && h[2 * u + 1] < h[t]) t = 2 * u + 1;
// 然后再判断一下当前根节点有没有右孩子,如果有判断一下上一步比较出来的做小值和当前右孩子的值的大小
if (u != t) {
swap(h[u], h[t]);
// 此时原来的元素 h[u] 就被换到了下标为 t 的数组中,所以继续 down(t)
down(t);
}
}
那么如何弹出栈顶元素呢?只要将第一个元素与最后一个元素交换,然后将指向堆中最后一个指针向前移动一个,再 down(1) 即可。这样就可以在删除时一直保证堆顶元素时最小的元素。
完整代码:
using namespace std;
const int N = 100010;
int n, m;
int h[N], cnt; // 最好不要使用 size 作为变量,因为有的头文件里会有size函数,容易冲突
void down(int u) {
int t = u;
// 找出根、左、右三个点做小的那个点
if (2 * u <= cnt && h[2 * u] < h[t]) t = 2 * u;
// 首先判断一下当前的根节点有没有左孩子,如果有判断一下根节点和左孩子的大小
if (2 * u + 1 <= cnt && h[2 * u + 1] < h[t]) t = 2 * u + 1;
// 然后再判断一下当前根节点有没有右孩子,如果有判断一下上一步比较出来的做小值和当前右孩子的值的大小
if (u != t) {
swap(h[u], h[t]);
// 此时原来的元素 h[u] 就被换到了下标为 t 的数组中,所以继续 down(t)
down(t);
}
}
int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) scanf("%d", &h[i]);
cnt = n;
for (int i = n / 2; i; i--) down(i);
// 先输入再维护小根堆的时间复杂度为 O(n),而一边输入一边维护的时间复杂度为 Nlog(N)
while (m--) {
printf("%d ", h[1]);
h[1] = h[cnt];
cnt--;
down(1);
}
return 0;
}
未完待续,持续更新中……
PS:如果没有你的关注,那我所做的将毫无意义,祝大家元宵节快乐!
以上是关于C++ STL详解的主要内容,如果未能解决你的问题,请参考以下文章