重点总结:
map
是STL的一个关联容器。里面的数据都是成对出现的,第一个是关键字(key),每个关键字只能在map中出现一次。第二个是该关键字的值(value)map
底层实现是红黑树
,这颗树具有对数据自动排序的功能,所以在map内部所有的数据都是有序的。map
的插入、删除操作复杂度为O(logN),查找的复杂度基本为O(logN)。
以下函数顺序与www.cplusplus中相同。
at 返回key对应value的引用
begin 返回指向map头部的迭代器
cbegin 返回指向容器头的迭代器-const
cend 返回指向容器尾元素后一个位置的迭代器 - const
clear 删除所有元素,size=0
count 返回对应key出现的次数,0或1
crbegin 返回指向容器最后一个元素的 逆序 迭代器 - const
crend 返回指向容器头元素前一个位置的 逆序 迭代器 - const
emplace 当容器中未包含参数key时,插入元素 move
emplace_hint 使用迭代器作为插入标示,当容器中无该key时,才会将其插入在标示位前
empty 如果map为空则返回true
end 返回指向map末尾的迭代器
equal_range 返回一个pair,包含两个迭代器,first是lower_bound(),second是upper_bound()
erase 删除元素
find 查找元素,找到返回迭代器,未找到返回map.end()
get_allocator
insert 插入元素
key_comp
lower_bound 返回一个迭代器,该迭代器指向>=给定key的 第一个位置
max_size 返回可以容纳的最大元素个数
operator=
operator[] 若key存在容器中,返回对应value的引用。否则,插入具有该key的新元素,并返回value的引用
rbegin 返回指向容器最后一个元素的 逆序 迭代器
rend 返回指向容器头元素前一个位置的 逆序 迭代器
size 返回map中元素的个数
swap
upper_bound 返回一个迭代器,该迭代器指向>给定key的 第一个位置
value_comp
#include
// key,value均可为自定义的对象或其他类型
// 当key自定义的对象时,需实现比较大小功能
explicit map(const key_compare& comp = key_compare(),
const allocator_type& alloc = allocator_type());
explicit map(const allocator_type& alloc); // [1]. 默认构造
template <class InputIterator>
map(InputIterator first, InputIterator last, // [2]. range
const key_compare& comp = key_compare(),
const allocator_type& = allocator_type());
map(const map& x); // [3]. copy
map(const map& x, const allocator_type& alloc);
map(map&& x); // [4]. move
map(map&& x, const allocator_type& alloc);
map(initializer_list<value_type> il, // [3]. initializer list
const key_compare& comp = key_compare(),
const allocator_type& alloc = allocator_type());
测试代码:
int main () {
std::map<char,int> first; // [1]. 默认构造
first['a']=10;
first['b']=30;
first['c']=50;
first['d']=70;
std::map<char,int> second(first.begin(),first.end()); // [2]. range
std::map<char,int> third(second); // [3]. copy
std::map<char,int,classcomp> fourth; // 使用自定义结构class
bool(*fn_pt)(char,char) = fncomp;
std::map<char,int,bool(*)(char,char)> fifth(fn_pt); // 使用函数指针进行 compare
return 0;
}
key
存在于容器中时,两函数均返回key
对应value
的引用。operator[]
,当参数key不存在时,构造.first
为key
的pair
插入到容器中,.second
(即val
)为默认值(或默认构造的对象),并返回对应value
的引用。at()
,如果该key不存在则抛出异常。 重点:使用operator[]
,即使不对其返回的引用进行操作,也会创建了一个新的元素,容器size
+1。例题代码如下:
int main() {
std::map<std::string,int> mymap = { { "alpha", 0 },
{ "beta", 0 } };
mymap.at("alpha") = 10; // at()
mymap.at("beta") = 20;
mymap["gamma"] = 30; // 1. add element: pair("gamma", 30)
mymap["Haha"]; // 2. add new element, second值为int 默认值0
mymap["Hehe"]++; // 3. add new element, second值为int 默认值0+1 ******************
for (auto& x: mymap) {
std::cout << x.first << ": " << x.second << '\n';
}
return 0;
}
Haha: 0
Hehe: 1
alpha: 10
beta: 20
gamma: 30
operator[]
、insert()
、emplace()
均可以实现元素插入。key
是唯一的,因此插入操作将检查容器中是否已存在与插入元素的key
相同的key,如果已存在,则不插入该元素,并返回该key
对应的迭代器。insert()
函数原型如下:
// [1]. single element 单个元素插入,返回插入位置iterator 和标示位
// 在数据的插入上涉及到集合的唯一性这个概念,即当map中有这个key时,插入失败,标示位为false
pair<iterator,bool> insert(const value_type& val);
template <class P> pair<iterator,bool> insert(P&& val);
// [2]. 通过迭代器位置插入单个元素,返回插入位置的iterator
iterator insert(const_iterator position, const value_type& val);
template <class P> iterator insert(const_iterator position, P&& val);
// [3]. 将迭代器范围[first terator, last terator)内的元素插入当前容器中
template <class InputIterator>
void insert(InputIterator first, InputIterator last);
// [4].initializer list,将list中元素插入
void insert(initializer_list<value_type> il);
int main() {
std::map<char,int> mymap;
// [1]
mymap.insert( std::pair<char,int>('a',100) ); // [1]. 单个元素插入
mymap.insert( std::pair<char,int>('z',200) );
std::pair<std::map<char,int>::iterator,bool> ret;
ret = mymap.insert( std::pair<char,int>('z',500) ); // [1]. 返回值
if (ret.second==false) {
std::cout << "[1] element 'z' already existed";
std::cout << " with a value of " << ret.first->second << '\n';
}
std::map<char, int>::iterator it = mymap.begin();
mymap.insert(it, std::pair<char, int>('b', 300)); // [2]. 效率最高
mymap.insert(it, std::pair<char, int>('c', 400));
std::cout << "mymap:\n";
for (it=mymap.begin(); it!=mymap.end(); ++it)
std::cout << "[2] " << it->first << " => " << it->second << '\n';
std::map<char, int> anothermap; // [3]. range
anothermap.insert(mymap.begin(), mymap.find('c'));
std::cout << "anothermap:\n";
for (it=anothermap.begin(); it!=anothermap.end(); ++it)
std::cout << "[3] " << it->first << " => " << it->second << '\n';
std::map<char, int> four_map; // [4]. initializer list
four_map.insert({ { 'd', 100 }, {'e', 200} });
std::cout << "four_map:\n";
for (it=four_map.begin(); it!=four_map.end(); ++it)
std::cout << "[4] " << it->first << " => " << it->second << '\n';
return 0;
}
[1] element ‘z’ already existed with a value of 200
mymap:
[2] a => 100
[2] b => 300
[2] c => 400
[2] z => 200
anothermap:
[3] a => 100
[3] b => 300
four_map:
[4] d => 100
[4] e => 200
emplace()
函数原型如下:std::map::emplace
template <class... Args>
pair<iterator,bool> emplace (Args&&... args);
emplace()
可避免复制和移动操作,在该文中有详细介绍:c++ 右值引用、移动语义、std::move、完美转发std::forward、emplace。
值得注意的是,只有当Map
中现有元素的键与这个元素的键不同时,才会构造这个元素。否则不会构造,下面是一个示例:
int main() {
std::map<char,int> mymap;
mymap.emplace('x',100);
mymap.emplace('y',200);
mymap.emplace('z',100);
auto ans = mymap.emplace('z',888888); // 无效
std::cout << ans.second << endl;
std::cout << "mymap contains:";
for (auto& x: mymap)
std::cout << " [" << x.first << ':' << x.second << ']';
std::cout << '\n';
return 0;
}
0
mymap contains: [x:100] [y:200] [z:100]
emplace_hint()
函数原型:std::map::emplace_hint
template <class... Args>
iterator emplace_hint(const_iterator position, Args&&... args);
emplace_hint()
使用一个迭代器作为插入标示位,只有当Map
中现有元素的键与这个元素的键不同时,才会构造这个元素。新元素会插入在标示位前。int main () {
std::map<char,int> mymap;
auto it = mymap.end();
it = mymap.emplace_hint(it,'b',10); // end()前插入
mymap.emplace_hint(it,'a',12); // 'b' 前插入
mymap.emplace_hint(mymap.end(),'c',14);
mymap.emplace_hint(mymap.end(),'c',15); // 插入失败
std::cout << "mymap contains:";
for (auto& x: mymap)
std::cout << " [" << x.first << ':' << x.second << ']';
std::cout << '\n';
return 0;
}
mymap contains: [a:12] [b:10] [c:14]
C++11
中,erase()
有以下几种类型:
// [1] 删除迭代器指向位置的元素,并返回一个指向下一元素的迭代器
iterator erase(const_iterator position);
// [2] 根据key来进行删除, 返回删除元素的数量(0或1)
size_type erase(const key_type& k);
// [3] 删除[first, last)范围内元素,返回指向下一元素的迭代器
iterator erase(const_iterator first, const_iterator last);
测试代码:
#include
#include
int main () {
std::map<char,int> mymap;
std::map<char,int>::iterator it;
// insert some values:
mymap['a']=10;
mymap['b']=20;
mymap['c']=30;
mymap['d']=40;
mymap['e']=50;
mymap['f']=60;
it=mymap.find('b');
mymap.erase(it); // 方法[1] erasing by iterator
mymap.erase('c'); // 方法[2] erasing by key
it=mymap.find('e');
mymap.erase(it, mymap.end()); // 方法[3] erasing by range
// show content:
for (it=mymap.begin(); it!=mymap.end(); ++it)
std::cout << it->first << " => " << it->second << '\n';
return 0;
}
a => 10
d => 40
[1].
find()函数通过key查找对应键值对key
存在于容器中,返回key
对应键值对的iterator
。map.end()
。int main() {
std::map<char,int> mymap;
std::map<char,int>::iterator it;
mymap['a']=50;
mymap['b']=100;
mymap['c']=150;
it = mymap.find('b');
if (it != mymap.end())
mymap.erase(it); // 若找到key='b', 则删除对应元素
// print content:
std::cout << "elements in mymap:" << '\n';
std::cout << "a => " << mymap.find('a')->second << '\n';
std::cout << "c => " << mymap.find('c')->second << '\n';
return 0;
}
elements in mymap:
a => 50
c => 150
[2].
count()返回key出现的次数int main() {
std::map<char,int> mymap;
char c;
mymap ['a']=101;
mymap ['c']=202;
mymap ['f']=303;
for (c='a'; c<'h'; c++) {
std::cout << c << ", ";
if (mymap.count(c)>0)
std::cout << " is an element of mymap.\n";
else
std::cout << " no.\n";
}
return 0;
}
a, is an element of mymap.
b, no.
c, is an element of mymap.
d, no.
e, no.
f, is an element of mymap.
g, no.
lower_bound()
返回一个迭代器,该迭代器指向>=给定key的 第一个位置。函数原型:// std::map::lower_bound
iterator lower_bound (const key_type& k);
const_iterator lower_bound (const key_type& k) const;
upper_bound()
返回一个迭代器,该迭代器指向>给定key的 第一个位置。函数原型:// std::map::upper_bound
iterator upper_bound (const key_type& k);
const_iterator upper_bound (const key_type& k) const;
例:
int main () {
std::map<char,int> mymap;
std::map<char,int>::iterator itlow,itup;
mymap['a']=20;
mymap['b']=40;
mymap['c']=60;
mymap['d']=80;
mymap['e']=100;
itlow=mymap.lower_bound ('b'); // >='b', 此处返回迭代器指向key为'b'的元素
itup=mymap.upper_bound ('d'); // >'d', 此处返回迭代器指向key为'e'的元素
mymap.erase(itlow,itup); // erases [b,e)
// print content:
for (std::map<char,int>::iterator it=mymap.begin(); it!=mymap.end(); ++it)
std::cout << it->first << " => " << it->second << '\n';
return 0;
}
a => 20
e => 100
int main () {
std::map<char,int> mymap;
std::map<char,int>::iterator it;
// insert some values:
mymap['a']=10;
mymap['c']=30;
mymap['b']=20;
mymap['d']=40;
mymap['e']=50;
mymap['f']=60;
// show content:
for (it=mymap.begin(); it!=mymap.end(); ++it)
std::cout << it->first << " => " << it->second << '\n';
return 0;
}
map容器中元素是有序的,所以打印也是有序的:
a => 10
b => 20
c => 30
d => 40
e => 50
f => 60