一、vector
向量容器
vector的元素不仅仅可以是int, double, string,还可以是结构体,但是要注意:结构体要定义为全局的,否则会出错。
cout<<vec[0]<<endl;
-
vector::iterator it;
-
for(it = vec.begin(); it!=vec.end(); it++)
-
cout<<*it<<
endl;
插入元素 ,在pos位置插入一个elem元素
vec.insert(pos, elem)
删除pos位置的元素
vec.erase(pos)
删除[begin, end)区间的元素
vec.erase(begin, end)
vec.size();
vec.clear();
vec.front()
删除最后一个元素
vec.pop_back()
尾部插入数据
vec.push_back(elem)
重新设置该容器的大小
vec.resize(num)
返回指向容器第一个元素的迭代器
vec.begin()
返回指向容器最后一个元素的迭代器
vec.end()
判断容器是否为空
vec.empty()
begin() 返回一个迭代器,它指向容器的第一个元素
reverse(vec.begin(), vec.end())
2、排序,需要头文件 #include<algorithm>
sort(vec.begin(), vec.end()); 默认是按升序排列,即从小到大
可以通过重写排序比较函数按照降序比较,如下:
定义排序比较函数:
-
bool Comp(const int &a, const int &b)
-
return a>b;
-
调用时:sort(vec.begin(), vec.end(), Comp),这样就实现了降序排序
-
# include <algorithm>
-
fill(vec.begin(), vec.end(), val);
//原来容器中每个元素被重置为val
fill_n函数的作用是:给你一个起始点,然后再给你一个数值count和val。把从起始点开始依次赋予count个元素val的值。
注意: 不能在没有元素的空容器上调用fill_n函数
fill_n(vec.begin, 10, val);
-
vector<
int> a={
1,
4,
4,
3,
2,
4,
2};
-
sort(a.begin(), a.end());
-
vector<
int>::iterator it = unique(a.begin(), a.end());
-
a.erase(it, a.end());
-
set
<int> valset = { 1,2,3,4,5,6 };
-
set
<int>::iterator iter;
-
for (iter = valset.begin(); iter != valset.end(); )
-
{
-
if (3 == *iter)
-
valset.erase(iter++);
-
else
-
++iter;
-
}
-
vector<
int> val = {
1,
2,
3,
4,
5,
6};
-
vector<
int>::iterator iter;
-
for(iter = val.begin();iter != val.end();){
-
cout<<*iter<<
endl;
-
if(
3 == *iter){
-
iter = val.erase(iter);
//返回下一个有效的迭代器,无需+1
-
}
else{
-
++iter;
-
}
-
}
-
vector<type> v;
-
//.....这里添加许多元素给v
-
//......这里删除v中的许多元素
-
vector<type>(v).swap(v);
-
//此时v的容量已经尽可能的符合其当前包含的元素数量
-
//对于string则可能像下面这样
-
string(s).swap(s)
即先创建一个临时拷贝与原先的vector一致,值得注意的是,此时的拷贝其容量是尽可能小的符合所需数据的。紧接着将该拷贝与原先的vector v进行交换。好了此时,执行交换时,临时变量会被销毁,内存得到释放。此时的v即为原先的临时拷贝,而交换后的临时拷贝则为容量非常大的vector(不过已经被销毁)
-
#include
<iostream>
-
#include
<vector>
-
-
using namespace std;
-
-
vector
<string> v;
-
char ch;
-
-
int main()
-
{
-
for(int i=0;i
<1000000;i++){
-
v.push_back("abcdefghijklmn");
-
}
-
cout<<v.capacity()<<endl;
-
//此时检查内存
-
v.erase(v.begin(), v.begin()+999900);
-
cout<<v.capacity()<<endl;
-
-
vector<string> (v).swap(v);
-
cout
<<v.capacity()<<endl;
-
-
return 0;
-
}
1048576
100
end() 返回set容器的最后一个元素
clear() 删除set容器中的所有元素
empty() 判断set容器是否为空
max_size() 返回set容器可能包含的元素最大个数
size() 返回当前set容器中的元素个数
erase(iterator), 删除定位器iterator指向的值
erase(first, second) 删除定位器first和second之间的值
erase(key_value) 删除键值key_value的值
find(), 返回给定值的定位器,如果没找到则返回end()
insert(key_value) 将key_value插入到set中,返回值是pair ::iterator, bool>,bool标志着插入是否成功,而iterator代表插入的位置,若key_value已经在set中,则iterator表示的key_value在set中的位置。
insert(first, second) 将定位器first到second之间的元素插入到set中,返回值是void
lower_bound(key_value) 返回第一个大于等于key_value的定位器
upper_bound(key_value) 返回最后一个大于等于key_value的定位器
三、map
(1)头文件 #include<map>
(2)创建map对象 map<int, string> m;
(3)基本操作
1、我们可以使用find()和count()方法来发现一个键是否存在。
查找map中是否包含某个关键字条目用find()方法,传入的参数是要查找的key
- begin() 返回指向map头部的迭代器,注意返回的数据类型是iterator
- end() 返回指向map末尾的迭代器,注意返回的数据类型是iterator
- find() 查找一个元素
- count() 返回指定元素出现的次数
例子:
-
int key=
2;
//要查找的key
-
//定义一个条目变量(实际是指针)
-
map<
int,
string>::iterator it;
-
it = map1.find(key);
-
if(it == map1.end()){
-
//没找到
-
}
-
else{
-
//找到
-
}
或者
-
map<
string,
string>m;
-
if(m[
112] ==
"")
-
cout<<
"we do not find 112"<<
endl;
2、从map中删除元素
移除某个map中某个条目用erase()
该方法的定义如下:
-
iterator erase(iterator it);
//通过一个条目对象删除
-
iterator erase(iterator first, iterator last);
//删除一个范围
-
size_type erase(const Key& key);
//通过关键字删除
-
map<
int,
string>::iterator it;
-
it = map1.find(
112);
-
if(it == map1.end())
-
cout<<
"we do not find 112"<<
endl;
-
else
-
map1.erase(it);
-
map<
int,
string> map1;
-
map1.insert(pair<
int,
string>(
102,
"aclive"));
-
map1.insert(
map<
int,
string>::value_type(
321,
"hai"));
-
map1[
112]=
"April";
//map中最简单最常见的插入添加
erase() 删除一个元素
size() 返回map中元素的个数
rend()返回一个指向map尾部的逆向迭代器
4、swap的用法
map中的swap不是一个容器中的元素交换,而是两个容器交换
5、map中的元素时自动按key升序排序,所以不能对map用sort函数。
6、map和unordered_map
unordered_map是C++ Boost库中的内容,这里的unordered翻译成“无序”。
但它并不是完全的“无序”的概念,而是散列式的存储方式。
unordered库提供了两个散列映射类,unordered_map和unordered_multimap。
它们的接口、用法与STL里的标准关联容器map和multimap相同,但是内部实现不同。
它们用散列表代替了二叉树的实现,模板参数多了散列计算函数,比较谓词使用equal_to<>。
看到这里,我们就应该明白,比起map/multimap,unordered_map和unordered_mutimap在查找元素的时候,速度不是一般的快。
它们的查找速率是常数级的,而map/multimap是基于二叉树实现的,所以查找是O(logn)
unordered库使用“桶”来存储元素,散列值相同的被存储在一个桶里。当散列容器中有大量数据时,同一个桶里的数据也会增多,造成访问冲突,降低性能。为了提高散列容器的性能,unordered库会在插入元素是自动增加桶的数量,不需要用户指定。但是,用户也可以在构造函数或者rehash()函数中,指定最小的桶的数量。
例子:
map代码:
-
#include<string>
-
#include<iostream>
-
#include<map>
-
using
namespace
std;
-
struct person
-
{
-
string name;
-
int age;
-
person(
string name,
int age)
-
{
-
this->name = name;
-
this->age = age;
-
}
-
bool
operator < (
const person& p)
const
-
{
-
return
this->age < p.age;
-
}
-
};
-
map<person,
int> m;
-
int main()
-
{
-
person p1("Tom1",20);
-
person p2("Tom2",22);
-
person p3("Tom3",22);
-
person p4("Tom4",23);
-
person p5("Tom5",24);
-
m.insert(make_pair(p3,
100));
-
m.insert(make_pair(p4,
100));
-
m.insert(make_pair(p5,
100));
-
m.insert(make_pair(p1,
100));
-
m.insert(make_pair(p2,
100));
-
for(
map<person,
int>::iterator iter = m.begin(); iter != m.end(); iter++)
-
{
-
cout<<iter->first.name<<
"\t"<<iter->first.age<<
endl;
-
}
-
return
0;
-
}
unordered_map代码:
-
#include<string>
-
#include<iostream>
-
#include<boost/unordered_map.hpp>
-
using
namespace
std;
-
struct person
-
{
-
string name;
-
int age;
-
person(
string name,
int age)
-
{
-
this->name = name;
-
this->age = age;
-
}
-
bool
operator== (
const person& p)
const
-
{
-
return name==p.name && age==p.age;
-
}
-
};
-
size_t hash_value(
const person& p)
-
{
-
size_t seed =
0;
-
boost::hash_combine(seed, boost::hash_value(p.name));
-
boost::hash_combine(seed, boost::hash_value(p.age));
-
return seed;
-
}
-
int main()
-
{
-
typedef boost::
unordered_map<person,
int> umap;
-
umap m;
-
person p1("Tom1",20);
-
person p2("Tom2",22);
-
person p3("Tom3",22);
-
person p4("Tom4",23);
-
person p5("Tom5",24);
-
m.insert(umap::value_type(p3,
100));
-
m.insert(umap::value_type(p4,
100));
-
m.insert(umap::value_type(p5,
100));
-
m.insert(umap::value_type(p1,
100));
-
m.insert(umap::value_type(p2,
100));
-
for(umap::iterator iter = m.begin(); iter != m.end(); iter++)
-
{
-
cout<<iter->first.name<<
"\t"<<iter->first.age<<
endl;
-
}
-
return
0;
-
}
前者的输出结果为:
Tom1 20
Tom3 22
Tom4 23
Tom5 24
后者的输出结果为:
Tom1 20
Tom5 24
Tom4 23
Tom2 22
Tom3 22
特性对比:
运行效率方面:unordered_map最高,map效率较低但提供了稳定效率和有序的序列。
占用内存方面:map内存占用略低,unordered_map内存占用略高,而且是线性成比例的。
若考虑有序,查询速度稳定,容器元素量少于1000,非频繁查询那么考虑使用map。若非常高频查询(100个元素以上,unordered_map都会比map快),内部元素可非有序,数据大超过1k甚至几十万上百万时候就要考虑使用unordered_map
c++ STL容器类的模板主要有:
头文件 | 内容 |
<vector> | vector<T>容器表示一个在必要时可自动增加容量的数组,只能在矢量容器的末尾添加新元素 |
<deque> | deque<T>容器实现一个双端队列。它等价于一个矢量,不过增加了向容器开头添加元素的能力 |
<list> | list<T>容器是一个双向链表 |
<map> | map<K, T>是一个关联容器,用关联链(类型为K)存储确定链/对象对所在位置的每个对象(类型为T)。 映射中的每个键的值必须唯一。 这个头文件也定义 multimap<K, T>容器,其中键/对象对中的键不需要唯一 |
<set> | set<T>容器是一个映射,其中各对象作为自身的键。集合中的所有对象必须唯一,使用对象作为自身的 键的一个后果是无法在集合中修改对象; 要修改对象,必须先删除它,然后插入修改后的版本。 |
<bitset> | 定义表示固定位数的bitset<T>类模板。它通常用来存储表示一组状态或条件的标记(flag) |