c++

参考链接:https://www.cnblogs.com/ZERO-/p/9347296.html
vector

vector可理解为变长数组,它的内部实现基于倍增思想。按照下列思路可以大致实现一个 vector的实际长度和最大长度。向 vector 加入元素前,若n=m,则在内存中申请2m的连续空间,并把内容转移到新的地址上(同时释放旧的空间),再执行插入。从 vector中删除元素后若n≤m/4,则释放一半的空间。

vector支持随机访问,即对于任意的下标0≤i<n,可以像数组一样用[i]取值。因为不是链表,不支持在任意位置O(1)插入。为了保证效率,元素的增删一般应该在末尾进行。

声明

#include<vector> 头文件

vector<int> a; 相当于1个长度动态变化的int数组
vector<int> b[233]; 相当于第1维长233,第二维长度动态变化的int数组
struct rec{...};
vector<rec> c; 自定义的结构体类型也可以保存在vector中

size/empty
size函数返回vector的实际长度(包含的元素个数),empty函数返回个bool类型,表明vector是否为空。二者的时间复杂度都是0(1).
所有的STL容器都支持这两个方法,含义也都相同,之后我们就不再重复给出
clear
clear函数把vector清空。
迭代器
迭代器就像STL容器的“指针”,可以用星号“*”操作符解除引用。一个保存int的vector的迭代器声明方法为:

vector<int>:iterator it;

vector的选代器是“随机访问迭代器”,可以把vector的迭代器与一个整数相减,其行为和指针的移动类似。可以把vector的两个迭代器相减,其结果也和指针相减类似,得到两个迭代器对应下标之间的距离。
begin/end
begin函数返回指向vector中第1个元素的迭代器。例如a是一个非空的vector,则*a.begin()与a[0]的作用相同。
所有的容器都可以视作一个“前闭后开”的结构,end函数返回vector的尾部,即第n个元素再往后的“边界”。*a.end()与a[n] 都是越界访问,其中n= a. size()
下面两份代码都遍历了vector a,并输出它的所有元素。

for (int i = 0; i < a.size(); i++)
cout << a[i]<<endl;
for (vector<int>::iterator it = a.begin(); it != a.end(); it++)
cout<<*it <<endl;

front/back
front函数返回vector 的第一个元素, 等价于a.begin()和a[0].
back函数返回vetor 的最后一个元素,等价于
--a.end()和a.[a.size()-1]
push back/pop back
a.push_back(x)把元素x插入到vector a的尾部。
a.pop_back()删除vector a的最后一个元素。


#include<queue>

头文件queue主要包括循环队列queue和优先队列priority_queue两个容器。
声明

queue<int> q;
struct rec{}; queue<rec>q
priority_ queue<int> q;
priority_ queue< pair<int,int> > q;
方法描述例子时间复杂度
[]随机访问与vector类似o(1)
begin/enddeque的头尾迭代器与vector类似o(1)
font/backdeque的头尾迭代器与vector类似o(1)
push_backdeque的头尾迭代器与vector类似o(1)
push_frontdeque的头尾迭代器与vector类似o(1)
pop_frontdeque的头尾迭代器与vector类似o(1)
pop_backdeque的头尾迭代器与vector类似o(1)
cleardeque的头尾迭代器与vector类似o(1)

#include<set>

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

声明

set<int> s;
struct rec{...}; set<rec> s ;
multiset<double> s;

与优先队列一样,set和multiset存储的元素必须定义“小于号”运算符。

size/empty/clear
与vector类似,分别为元素个数、是否为空、清空。前两者的时间复杂度0(1).
迭代器
set和multiset的选代器称为“双向访问迭代器”,不支持“随机访问”号,支持(*)解除引用,仅支持“++”和“-”两个与算术相关的操作。
设it是一个迭代器,例如set<int>::iterator it;如把it++,it会指向下一个元素。
“下一个”的元素。在排序的结果中,排在it下一名的元素。同理,若把i–, 则it将指向上一名元素
请注意,执行“++”和“–”操作的时间复杂度都是O(nlogn)。 执行操必仔细检查,避免迭代器指向的位置超出首、尾迭代器之间的范围。
begin/end
返回集合的首、尾迭代器,时间复杂度为0(1)。s.begin()是指向集合中最小元素的迭代器。
s.end()是指向集合中最大元素的下一个位置的迭代器。
换言之,就像vector一样是一个前闭后开的集合。
insert
insert把个元素 x插入到集合s中,时间复杂度为O(nlogn).在s中,若元素已存在,则不会重复插入该元素,对集合的状态无影响。
下面的代码把n个整数插入有序多重集multiset, 并从小到大输出,时间复杂度为0(nlogn),相当于进行了一次排序。假设n个整数目前存储在数组a[1~n] 中。

multiset<int> s;
for (int i=1; i <=n; i++) s.insert(a[i]);
for (multiset<int>::iterator it = s.begin(); it != s.end(); it++)cout < *it << endl;

find
s.find(x)在集合s中查找等于x的元素,并返回指向该元素的迭代器。若不存在,则返回s.end()。时间复杂度为0(nlogn)。

lower_bound/upper_bound
这两个函数的用法与find 类似,但查找的条件略有不同,时间复杂度0(logn)。s.lower_ bound(x)查找<=x的元素中最大的一个,并返回指向该元素的迭代器。s.upper_bound(x)查找>x的元素中最小的一个,并返回指向该元素的迭代器。

erase
设it是一个迭代器,s.erase(it) 从s中删除迭代器it 指向的元素,时间复杂度为0(logn)。
设x是一个元素,s.erase(x) 从S中删除所有等于x的元素,时间复杂度为
0(k +logn),其中k为被删除的元素个数。
如果想从multiset中删掉至多1个等于x的元素,可以执行:if ((it = s.find(x)) != s.end()) s.erase(it);

count
s.count(x)返回集合s中等于x的元素个数,时间复杂度为0(k + logn),其中k为元素x的个数。

#include<map>

map容器是个键值对key-value的映射。其内部实现是一棵以 key为关健码的红黑树,其中key必须定义“小于号”运算行
声明方法为:
map<key_ type, value_type> name;
例如:

map<long long, bool> vis;
map<string, int> hash;
map< pair<int, int>, vector<int> > test;

在很多时候,map 容器被当作Hash表使用,建立从复杂信息key (如字符)到简单信息value (如定范围内的整数)的映射。
因为map基于平衡树实现,所以它的大部分操作的时间复杂度都在0(logn)级则,略慢于使用Hash函数实现的传统Hash表。从C++11开始,STL中新增了unordered_map等基于Hash 的容器,但部分算法竞赛并不支持C++11标准。这里就不再介绍这些新容器。

size/empty/clear/begin/end
与set类似。分别为元素个数、是否为空、清空、首选代器、尾选代器。
迭代器
map的选代器与set一样, 也是“双向访问选代器”.对map的送代器解除引用后将得到一个二元组pair<key_type, value_type>
insert/erase
与set类似,分别为插入、删除。insert的参数是
pair<key _type, value_type>,erase的参数可以是pair或者迭代器。

map<int, int> h;
h.insert(make pair(1,2)),h.insert(make_ pair(2,3));
map<int, int>::iterator it = h.begin();
pair<int,int> p = *it;
h.erase(it), h.erase(make_pair(2,3));
cout<< p.first<<''<<p. second<<endl ;

find()
h.find(x)在map中查找key为x的二元组,并且返回指向这个二元组的迭代器。如不存在,返回h.end()。时间复杂度为O(logn)
[]操作符
h[key]返回key映射到的value的引用,时间复杂度为0(logn)。
[]操作符是map最吸引人的地方。我们可以很方便地通过h[key]来得到key对应的value,还可以对h[key]进行赋值操作,改变key对应的value.
需要特别注意的是,若查找的key不存在,则执行h[key]后,h会自动新建一个二元组(key,zero),并返回zero的引用。这里zero表示一个广义“零值”,如整数0、空字符串等。如果查找之后不对h[key]进行赋值,那么时间一长,h会包含很多无用的“零值二元组”,白白地占用了空间,降低了程序运行效率。强烈建议读者在用0操作符查询之前,先用find方法检查key的存在性。

[实例]用map统计字符串出现的次数
给定n个字符串,m个问题,每个问题询问一个字符串出现的次数。n≤20000, m≤20000,每个字符串的长度都不超过20。

map<string, int> h;
char str[25];
for (int i= 1; i<= n; i++) {
scanf(“%s”, str); h[str]++;
}
for (int i= 1;i<=m; i++) {
scanf(“%s”, str);
if (h.find(str) == h.end()) puts(“0”);else printf( “%d\n”, h[str]);
}

#include<bitset>

bitset可看作一个多位二进制数,每8位占用1个字节,相当于采用了状态压缩的二进制数组,并支持基本的位运算。在估算程序运行的时间时,我们一般以32位整数的运算次数为基准,因此n位bitset执行一次位运算的复杂度可视为n/32,效率较高。

声明
bitset<10000> s;
表示一个10000位二进制数,<>中填写位数。下面把位数记为n。
位运算操作符
~s:返回对bitsets接位取反的结果。
&|^返回对两个位数相同的bitset执行按位与、或、异或运算的结
[]操作符
s[k]表示。的那k位,既可以取值,也可以赋值。
10000 二进制中,最低位为0最高位为9999

count
s.count()"返回有多少位为1。

any/none
若s所有位都为0,则s.any()返回false, s.none()返回 true
若s至少一位为1, 则s.any()返回true, s.none()返回 false.

#include<algorithm>

下面介绍的几个函数都作用在序列上,接受两个选代器(或指针) l,r,对下标的前闭后开区间n中的元素执行系列操作。

reverse翻转
翻转一个vector:
reverse(a.begin(), a.end());
翻转一个数组,元素存放在下标1~n:reverse(a+1, a+n+1);
unique 去重
返回去重之后的尾迭代器(或指针),仍然为前闭后开,即这个尾选代器是去重之后末尾元素的下一个位置。该函数常用于离散化,利用迭代器(或指针)的减法,可计算出去重后的元素个数 m.
把一个vector去重:
int m = unique(a.begin(), a.end())-a.begin();
把一个数组去重,元素存放在下标 1~n:
int m= unique(a+1, a+n+1)-(a+1);

random_shufle随机打乱
用法与reverse相同。
next_permutation下一个排列

sort快速排序
对两个迭代器(或指针)指定的部分进行快速排序。可以在第三个参数传入定义大小比较的函数,或者重载“小于号”运算符。

把一个int数组(元素存放在下标1~n)从大到小排序,传入比较函数:
int a[MAX_ SIZE];
bool cmp(int a, int b) { return a > b; }
sort(a+1, a+n+1, cmp);

把自定义的结构体vector排序,重载“小于号”运算符:

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+n+1, x) - a;
在有序vector中查找小于等于x的最大整数(假设一定存在)
int y=upper_bound(a.begin(), a.end(), x);

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值