C/C++语法:(五)STL
1.vector
如果想要开一个int二维数组,两个维度均为\(10^5\),则总大小为\(10^{10}\)个int,总容量为40G,显然没有那么大的空间给你使用,这时vector的作用就体现出来了:vector是变长数组,用多少开多少,可以保证大小为\(10^5\)的整数倍.
#include <vector>
int main(){
vector <int> a;
vector <int> b[233]; //第一维长233,第二维动态变化的int数组
struct Rec{
int x, y;
};
vetor <Rec> c;
a.size();
a.empty();//所有容器都支持以上两种方法
a.clear(); //清空
}
迭代器:可类比为STL容器中的指针,虽然在算法题中基本用不到迭代器:
vector<int>::iterator it = a.begin(); //begin()返回指向第一个元素的迭代器
a.front(); //等价于*a.begin();
vector<int>::iterator it = a.end(); //end()返回的是最后一个元素的后一个位置,*a.end()为越界访问)
a.back(); //返回最后一个元素 等价于a[a.size() - 1]
遍历vector:
//1.
vector<int>a({1,2,3});
for (int i = 0; i < a.size(); i ++) cout << a[i];
//2.
for (vector<int>::iterator i = a.begin(); i != a.end(); i ++)
cout << *i;
//注意vector<int>::iterator可以用auto代替,auto写迭代器真是太愉快了
//3.
for (int x : a) cout << x;
增加、删除:
a.push_back(4); //在最后加一个元素 复杂度为O(1)
a.pop_back(); //删除最后一个元素 复杂度为O(1)
2.队列queue
小学二年级学的数据结构告诉我们,队列是一种先进先出的结构.
#include <queue>
int main(){
queue <int> q;
}
优先队列定义:
//默认优先弹出队列里的最大值
priority_queue <int> q;
//弹出最小值
priority_queue<int, vector<int>, greater<int>> b;
//如果是自定义的结构体的循环队列,一定要重载<符号,因为是大根堆,不能重载>
struct Rec{
int a, b;
bool operator< (const Rect& t) const{
return a < t.a;
}
};
//如果是优先队列,则重载>符号 背过就完事
循环队列常用操作:
q.push(4); //插入队尾
q.pop(); //弹出队头元素
cout << q.front() << endl;
a.back() //返回队尾元素
优先队列常用操作:
q.push(); //优先队列就不一定是插到队尾了 因为它是堆的结构
q.pop(); //删除堆顶元素(最大值)
q.top(); //查询堆顶元素(最大值)
循环队列、优先队列都没有clear()函数. 栈也没有clear()函数,这两个是关系户.你要清空你就重新初始化一遍呗.
3.栈stack
和队列相反,先进后出:
#include <stack>
int main(){
stack<int> stk;
stk.push(4);
stk.pop(); //删除栈顶元素
stk.top(); //返回栈顶元素
}
4.deque
又称双端队列,因为两端都是可进可出的,故得名,但是速度慢的令人发指,所以比赛中其实也不咋用得到.
#include <deque>
int main(){
deque <int> a;
a.begin(), a.end();
a.front(), a.back();
a.push_back(1), a.push_front(2);
a.clear();
}
双端队列有clear()函数.
5.set
该容器的实现基于红黑树,不过你知道了也没啥用,顶多能用来猜测"删除"这类的函数时间复杂度为\(O(logn)\).
#include <set>
int main(){
//1.定义
set<int> a; //元素不能重复 否则会被忽略
multiset<int> m; //元素可以重复
//2.size empty clear与上述几个容器相同
//3.结构体
struct Rec{
int a, b;
bool operator< (const Rec& t) const{
return x < t.x;
}
};
set<Rec> s;
//4.迭代器
set<int>::iterator it = a.begin();
it ++; it --;
a.end();
//5.插入与查找
a.insert(x);
a.find(x); //返回迭代器 如果没找到的话返回a.end() 故有以下应用:
if (a.find(x) == a.end()) //判断x在set中
//6.erase 删除迭代器it所指向的元素 也可以直接删元素x 如果x不存在也不会报错 复杂度为O(logn)
a.erase(it);
a.erase(x);
//7.count(x) 由于set的特性 所以这个计数函数反而是用来判断元素存不存在
//存在返回1 不存在就是0了
a.count(x);
}
由于set是一个有序序列,所以很自然的,我们想起了幼儿园时支配我们的二分算法:
a.lower_bound(x); //大于等于x的最小的元素的迭代器
a.upper_bound(x); //大于x的最小的元素的迭代器
6.unordered_set
低层实现为哈希表,和set的区别就在于它是无序的,因此是O(1)的,所以就没有什么lower_bound了.
#include <unordered_set>
int main(){
unordered_set<int> a;
unordered_multiset<int> a; //不能存储重复元素
}
7.pair
int main(){
pair<int, string>a;
//1.定义
a = {3, "yxc"}; //c++ 11
a = make_pair(4, "abc"); //c++ 99
cout << a.first << ' ' << a.second << endl;
//2.比较 双端比较 按维度先后进行
a==b; a>=b; a<=b;
}
8.map
非常有用,低层仍然是红黑树
#include <map>
#include <unordered_map>
int main(){
map <string, int> a;
//1.插入 O(logn)
a["Wx"] = 1;
a.insert({"asd", 1});
//2.查找 key为x
a,find(x);
//
unordered_map<int, int> c;
}
9.bitset
常用于处理位运算:
#include <bitset>
int main(){
bitset<1000> a; //长度是1000位的串
a[0] = 1
cout << a[0] << endl;
a.set(3); //把第3位设成1
a.reset(3); //把第3位设成0
}
本文算法思想源于Acwing,特此注明。

浙公网安备 33010602011771号