根据应用场景的不同,STL共实现了两种不同结构的管理式容器:树型结构与哈希结构。树型结构的关联式容器主要有四种:map、set、multimap、multiset。这四种容器的共同点是:使用平衡二叉树(红黑树)作为其底层结构,容器中的元素是一个有序的序列。
template <class T1, class T2>
struct pair {
typedef T1 first_type;
typedef T2 second_type;
T1 first;
T2 second;
pair() : first(T1()), second(T2()) {}
pair(const T1& a, const T2& b) : first(a), second(b) {}
#ifdef __STL_MEMBER_TEMPLATES
template <class U1, class U2>
pair(const pair<U1, U2>& p) : first(p.first), second(p.second) {}
#endif
};
class map {
public:
// typedefs:
typedef Key key_type;
typedef T data_type;
typedef T mapped_type;
typedef pair<const Key, T> value_type;
typedef Compare key_compare;
class value_compare
: public binary_function<value_type, value_type, bool> {
friend class map<Key, T, Compare, Alloc>;
protected :
Compare comp;
value_compare(Compare c) : comp(c) {}
public:
bool operator()(const value_type& x, const value_type& y) const {
return comp(x.first, y.first);
}
};
private:
typedef rb_tree<key_type, value_type,
select1st<value_type>, key_compare, Alloc> rep_type;
rep_type t; // red-black tree representing map
// 注意这个重载函数
T& operator[](const key_type& k) {
return (*((insert(value_type(k, T()))).first)).second;
}
};
std::map
template <class Key,
class T,
class Compare = less<Key>,
class Alloc = allocator<pair<const Key, T> >
> class map;
key:键值对中的key的类型
T:键值中value的类型
Compare:比较器的类型,map中的元素是按照key来比较的,缺省情况下按照小于来比较,一般情况下(内置类型元素)
该参数不需要传递,如果无法比较时(自定义类型),需要用户自己显式传递比较规则(一般情况下按照函数指针或者仿函数来传递)
Alloc:通过空间配置器来申请底层空间,不需要用户传递,除非用户不想使用标注库提供的空间配置器
函数名称 | 函数声明 |
---|---|
map(const key_compare& comp = key_compare(), allocator_type &alloc = allocator_type()) const | 构造一个空的map |
template map(InputIterator first, InputIterator last, const key_compare& comp = key_compare(), const alloctor_type &alloc = alloctor_type()) | 用first到last区间中的元素构造map |
map(const map&x) | map的拷贝构造 |
void test01()
{
// key和value的类型给成字符串
map<string,string> m1;
// C++11 的列表初始化
map<string,string> m2{{"apple", "苹果"},
{"banana", "香蕉"},
{"orange", "橘子"},
{"peach", "桃子"}};
//cout << m2["apple"] << endl;
for(auto it = m2.begin(); it != m2.end(); ++it)
{
cout << (*it).first << "--->" << it->second << endl;
}
map<string,string> m3(m2);
}
函数名称 | 函数声明 |
---|---|
bool empty()const | 检测map中的元素是否为空,如果为空返回true,否则返回false |
size_type size()const | 返回map中有效元素的个数 |
函数名称 | 函数声明 |
---|---|
pair |
在map中插入键值对x,iterator代表插入元素的位置,bool代表是否插入成功 |
iterator insert(iterator position, const value_type &x | 在position位置插入值为x的键值对,返回该键值对在map中的位置,注意:元素不一定必须插入在position位置,该位置指示一个参考 |
template void insert(InputIterator first, InputIterator last) | 在map中插入first到last区间中的元素 |
void erase(iterator position) | 删除position位置上的元素 |
void erase(iterator first,iteraator last) | 删除first到last区间中的元素 |
void swap(map |
交换两个map中的元素 |
void clear() | 将map中的元素清空 |
iterator find(const key_type& x) | 在map中查找key为x的元素,找到返回该元素的位置迭代器,否则返回end |
const_iterator find(const key_type& x) | 在map中查找key为x的元素,找到返回该元素的位置const迭代器,否则返回cend |
size_type count(const key_type &x)const | 返回Key为x的键值在map中的个数,注意map 中的key是唯一的,因此该函数的返回值要么为0,要么为1,因此可以用该函数来检测一个key是否在map中 |
mapped_type& at (const key_type& k) | 返回键值k对应value的引用,如果k不在map中,那么out_of_range exception异常抛出(C++11新特性) |
mapped_type& operator[](const key_type& k) | 返回key对应的value,可以通过返回查看当前元素是否在map中 |
void test03()
{
map<string,string> m;
// 向map中插入元素的方式
// 将键值对<"peach", "桃子">插入到Map,用pair直接来构造键值对
m.insert(pair<string, string>("peach", "桃子"));
//将键值对<"watermel", "西瓜">插入到map中,用make_pair函数来构造键值对
m.insert(make_pair("watermel", "西瓜"));
// 先拿到该容器中的键值对类型,然后插入
m.insert(map<string,string>::value_type("peach", "桃子"));
// key不存在时抛异常
//m.at("banan") = "香蕉";
// 这个的原理是,先用key和T()构造一个键值对,然后调用insert函数将该键值对插入到map中
// 如果key已经存在,插入失败,insert函数返回该key所在位置的迭代器,
// 如果key不存在,插入成功,insert函数返回新插入元素所在位置的迭代器,
// operator[]函数最后将insert的返回值中的value返回
m["banan"] = "香蕉";
// 输出Map的大小
cout << m.size() << endl;
// 用迭代器去遍历map中的元素,可以得到一个按照key排序的序列
for(auto &e : m)
{
cout << e.first << "--->" << e.second << endl;
}
cout << endl;
// map中的键值对key一定是唯一的,如果key存在将插入失败
auto ret = m.insert(make_pair("peach", "桃色"));
if(ret.second)
{
cout << "不在map中,已经插入" << endl;
}
else
{
cout << "键值为peach已经在map:" << ret.first->first << ":" << ret.first->second << endl;
}
// 删除key为apple的元素
m.erase("apple");
for(auto&e : m)
{
cout << e.first << "--->" << e.second << endl;
}
if(1 == m.count("apple"))
{
cout << "apple还在" << endl;
}
else
{
cout << "apple被吃了" << endl;
}
}
自定义排序
class myCompare
{
public:
bool operator()(int v1, int v2)
{
return v1 > v2;
}
};
void test3_1()
{
map<int, int, myCompare> m;
m.insert(pair<int, int>(1,10));
m.insert(make_pair(2,20));
m.insert(map<int,int>::value_type(3,30));
m[4] = 40;
for(map<int, int, myCompare>::iterator it = m.begin(); it != m.end(); it++)
{
cout << "key :" << it->first << "value :" << it->second << endl;
}
}
map插入数据的三种方法
区别:以上三种用法,虽然都可以实现数据的插入,但是它们是有区别的。第一种和第二种在效果上是完成一样的,用 insert 函数插入数据,在数据的插入上涉及到集合的唯一性这个概念,即当 map 中已经存在某个关键字时,insert 操作是不能成功插入数据,但是用数组方式则可以,它可以覆盖以前该关键字对应的值。
void test04()
{
multimap<string, string> m;
m.insert(make_pair("李逵", "黑旋风"));
m.insert(make_pair("林冲", "豹子头"));
m.insert(make_pair("鲁达", "花和尚"));
m.insert(make_pair("李逵", "铁牛"));
cout << m.size() << endl;
for(auto& e : m)
{
cout << "<" << e.first << "," << e.second << ">" << endl;
}
cout << m.count("李逵") << endl;
}
void test05()
{
multimap<int, int> m;
for(int i = 0; i < 10; ++i)
{
m.insert(pair<int,int>(i, i));
}
for(auto& e : m)
{
cout << e.first << "--->" << e.second << endl;
}
cout << endl;
auto it = m.lower_bound(5);
cout << it->first << "--->" << it->second << endl;
//返回m中大于5的元素
it = m.upper_bound(5);
cout << it->first << "--->" << it->second << endl;
}