vector:变长数组:倍增的思想;
vector<变量类型> 变量名(长度,初始值) //也可以没有长度和初始值
vector<int> a(10, -1);
vector<char> a;
vector <int> a[10]; //vector也可以定义数组表示有10个这样的vector;
//成员函数:
vector<int> a;
a.size()://求vector的长度;即元素的个数
a.empty()://a是否为空,为空则返回true;否则false;
a.clear(): //清空数组!
a.front()://返回第一个数
a.back()://返回vector的最后一个数
a.push_back(元素)://在末尾插入一个数
a.pop_back()://删除最后一个数!
a.begin(), a.end()://vector的迭代器:beginr的第一个数,end是vector的最后一个数的后面一个数!!
//遍历方式:
for (int i=0; i < a.size(); i ++) cout << a[i] << ' ';
cout << endl;
for (vector<int>::iterator i = a.begin(); i != a.end(); i ++) cout << *i << ' ';
for (auto i = a.begin; i != a.end(); i ++) cout << *i << ' ';
cout << endl;
//vector 的黑科技:
vector<int>a(4,3), b(3,4) //按照字典序进行比较!字典序比较从第一个数开始比,比首字母就行了!
if (a < b) puts("a < b");
//注意系统为某一程序分配空间时,所需时间与空间大小无关,与分配的次数有关。例如:1000个a[1]和1个a[1000];
auto可以遍历所有的容器:
for (auto x:a) cout << x;
pair <int, int>
pair是一个二元组!
可以定一个int和string:pair<int, string> p;
p.first; //取出第一个元素;
p.second;//取出第二个元素;
支持比较运算,以first为第一关键字,second为第二个关键字,按照字典序比较!
用途:如果某个事物有两种属性,则可以用pair来存,然后需要按照某种属性排序的话,就将需要排序的属性放到第一个关键字里,不排序的属性放到另一个关键字里!
pair<int, string> p;
p.first;
p.second;
//构造pair:
p = make_pair(10, "ljx");
p = {10, "abc"} ; //c++11里可以直接写!
pair也可以存储三个属性:
pair<int, pair<int, int>> p;
string:字符串, substr(返回某一个子串)c_str(返回string对应的字符数组的头指针)
a.size(); = a.length
a.empty();
a.clear();
string a = "ljx";
a += "def"; //直接添加元素!
a += "c";
a.substr(1, 2); //第一个参数表示的是起点,第二个参数表示所截取字符串的长度!也可以把第二个参数省略掉,直接返回从1起点开始以后的子串!
printf ("%s", a.c_str());//用cstring可以返回字符数组的起始地址!
queue:
队尾入队,push();
队头出队pop();
返回队头元素,front();
返回队尾元素:back();
size(), empty();
priority_queue:优先队列,实际是一个堆;
头文件:< queue >
默认是大根堆,即最大的元素在根结点,与小根堆相反!
push() 是往堆里插入一个元素;
top() 是返回堆顶元素;
pop()弹出堆顶元素;
//若想定义一个小根堆怎么办呢?小根堆的原理是:最小的元素在根结点,是一棵二叉树的形式!
//方法一:
//那我们将所要插入的每个元素都取负,即可得到越大的元素负的越大,越小的元素反而变大了,所以小的元素自然在根结点了
priority_queue<int> heap;
heap.push(-x);
//方法二:直接定义成小根堆!
//定义的时候多加两个参数!
#include<vector>
priority_queue<int, vector<int>, greater<int>> heap; //这就是小根堆了
stack:栈:
push:入栈;
pop()弹出栈顶元素;
top:返回栈顶元素!
size(),empty();
deque:双端队列:队头队尾都可以插入删除!而且可以随机访问,加强版的vector;
头文件:
< deque >
size();
empty();
clear();
front(); 返回第一个元素
back();返回最后一个元素
push_back; 向最后插入一个元素;
push_front; 从队首插入一个元素;
pop_bck(); 弹出最后一个元素;
pop_front(); 弹出第一个元素!
还可以支持随机存取:[] //但效率低下!速度慢!
还支持begin和end这个迭代器
小根堆:
set、map、multiset、multimap:上述均是基于平衡二叉树(红黑树)实现的,他们的本质是动态维护有序序列;
#include<set>
set<int> s; //set里面是不会有重复元素的,若你插入一个重复元素,则会被忽略掉
multiset<int> ms; //multiset是可以有重复元素的!
size();
empty();
clear();
begin()/end(): 支持++--操作;返回前驱和后继
有序表里的前驱指的是前面一个数,后继指的是后面一个数!
set/multiset的函数:
insert(); //插入一个数,时间复杂度 log(n);
find(); //查找一个数!
count(); //返回某一个元素的个数,set里面只有0和1两种情况,而multiset里面有很多个元素!
erase();
/*
(1) set里输入一个数,删除这个数,multiset里是输入一个数x,删除所有的数x;
(2) 输入一个迭代器,删除 *这个* 迭代器.
*/
set最核心的两个操作:
lower_bound() / upper_bound();
lower_bound(x); //返回大于等于x的最小的数的迭代器;
upper_bound(x); //返回大于x的最小的数的迭代器;
#include<map>
map 和 multimap:map里面是两个东西,两个东西做映射!
insert(); //插入的数是一个pair,因为是两个数的嘛,map存的是一个映射,把A映射到B;
erase(); //输入的参数是pair或者迭代器都可以;
find (); //
[] ://可以像用数组一样用这个map;时间复杂度在map里面是 O(log n)的,数组里是 O(1)的
//举例:map:
#inlcude<map>
map<string, int> a; //将string映射成整数int;
a["ljx"] = 1; //即将string:ljx映射成了int 1;
cout << a["ljx"] << endl; //查找的话,可以直接查找到ljx,就像索引一样!输出为1;
unordered_set/map/multiset/multimap :哈希表!(和上面类似)
和上面类似,不过增删改查的时间复杂度是 O(1)的;
缺点是:不支持lower_bound () 和 upper_bound ();也不支持迭代器的+±-;提供++ 不提供 --;
bitset:压位!
举例:
假设现在开一个bool数组,长度为1024;其中每个bool变量在C++里是1B;所以1024长度的bool数组,需要1KB的大小空间!1024B = 1KB;
若我们把每个字节存8位,那我们只需要开128个字节就可以了;
这就是压位,这就是bitset;
什么时候会用呢?
假如我们要存一个bool变量的1w*1w的数组;
那么用bool来存的话,我们需要 10 ^8B ~ 100 MB;
但是空间有限制为64MB,所以我们可以用bitset来存!
每个字节存8位,那么只需要12MB就可以了!
用法:
bitset<10000> s; //别的括号里 写的是类型,这个括号里写的是个数!
~, &, |, ^, >>, << ==, !=, [也支持中括号操作],
count()://返回有多少个1
any(): 判断是否至少有一个1;
none(): 判断是否全为0;
set ():把所有位置为1;
set(k, v);把第k位变成v;
reset(); 把所有位变成0;
flip(); 等价于~
flip(); 把第k位取反
list: