本篇文章进行C++STL中set和map的学习!!!
概念:
概念:
SGI-STL中关于键值对的定义:
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)
{}
};
注意:我们不需要自己实现,了解就好,标准库中已经对其实现
概念:
【set的文档】
概念:
特点:
template < class T, // set::key_type/value_type
class Compare = less<T>, // set::key_compare/value_compare
class Alloc = allocator<T> // set::allocator_type
> class set;
注意:
| 函数声明 | 功能介绍 |
|---|---|
| set (const Compare& comp = Compare(), const Allocator&= Allocator() ); | 构造空的set |
| set (InputIterator first, InputIterator last, const Compare& comp = Compare(), const Allocator& =Allocator() ); | 用[first, last)区间中的元素构造set |
| set ( const set | set的拷贝构造函数 |
void Testset()
{
int Array[] = { 1, 2, 3 ,4, 5 };
set<int> s1;
set<int> s2(Array, Array + sizeof(Array) / sizeof(int));
set<int> s3;
s3 = s2;
}

| 函数声明 | 功能介绍 |
|---|---|
| iterator begin() | 返回set中起始位置元素的迭代器 |
| iterator end() | 返回set中最后一个元素后面的迭代器 |
| const_iterator cbegin() const | 返回set中起始位置元素的const迭代器 |
| const_iterator cend() const | 返回set中最后一个元素后面的const迭代器 |
| reverse_iterator rbegin() | 返回set第一个元素的反向迭代器,即end |
| reverse_iterator rend() | 返回set最后一个元素下一个位置的反向迭代器,即rbegin |
| const_reverse_iterator crbegin() const | 返回set第一个元素的反向const迭代器,即cend |
| const_reverse_iterator crend() const | 返回set最后一个元素下一个位置的反向const迭代器,即crbegin |
注:这里就不演示迭代器了,与前面的序列式容器使用方法一样
| 函数声明 | 功能介绍 |
|---|---|
| bool empty ( ) const | 检测set是否为空,空返回true,否则返回true |
| size_type size() const | 返回set中有效元素的个数 |

| 函数声明 | 功能介绍 |
|---|---|
| pair | 在set中插入元素x,实际插入的是 |
| void erase ( iterator position ) | 删除set中position位置上的元素 |
| size_type erase ( constkey_type& x ) | 删除set中值为x的元素,返回删除的元素的个数 |
| void erase (iterator first,iterator last) | 删除set中[first, last)区间中的元素 |
| void swap (set | 交换set中的元素 |
| void clear ( ) | 清空set中的元素 |
| iterator find ( constkey_type& x ) const | 返回set中值为x的元素的位置 |
| size_type count ( constkey_type& x ) const | 返回set中值为x的元素的个数 |
template <typename T>
void Show(set<T>& s)
{
typename set<T>::iterator It = s.begin();
while (It != s.end()) {
cout << *It << ' ';
++It;
}
cout << endl;
}
void Testset2()
{
set<int> s;
for (int i = 1; i <= 5; ++i) {
s.insert(i);
}
Show(s);
int x;
while (cin >> x) {
if (s.empty()) break;
set<int>::iterator Pos = s.find(x);
if (Pos != s.end())
{
s.erase(Pos);
Show(s);
cout << "删除" << x << "成功!!!" << endl;
}
else {
cout << "删除" << x << "失败!!!" << endl;
}
}
}

【mulriset文档介绍】
概念:
特点:
multiset的接口与set一样,主要区别是multiset的插入可以"数据冗余",并且不能"去重"
template <typename T>
void Show(multiset<T>& s)
{
typename multiset<T>::iterator It = s.begin();
while (It != s.end()) {
cout << *It << ' ';
++It;
}
cout << endl;
}
void Testmultiset()
{
multiset<int> ms;
ms.insert(5);
ms.insert(3);
ms.insert(4);
ms.insert(1);
ms.insert(1);
ms.insert(2);
ms.insert(1);
Show(ms);
cout << ms.erase(1) << endl; // 删除了三个1,erase返回删除的数量
cout << ms.count(1) << endl; // 查找1在ms中的个数
Show(ms);
}

【map文档介绍】
概念:
typedef pair<const key, T> value_type
template < class Key, // map::key_type
class T, // map::mapped_type
class Compare = less<Key>, // map::key_compare
class Alloc = allocator<pair<const Key,T> > // map::allocator_type
> class map;
void Testmap()
{
// 构造空的map
map<int, int> m1;
m1[1] = 2;
m1[2] = 3;
// 通过区间迭代器来构造
map<int, int> m2(m1.begin(), m1.end());
// 拷贝构造
map<int, int> m3(m2);
}

| 函数调用 | 功能说明 |
|---|---|
| begin() | 返回容器中首元素的位置 |
| end() | 返回容器中最后一个元素的下一个位置 |
| cbegin() | 与begin意义相同,但cbegin所指向的元素不能修改 |
| cend() | 与end意义相同,但cend所指向的元素不能修改 |
| rbegin() | 反向迭代器,rbegin在end位置,其++和–操作与begin和end操作移动相反 |
| rend() | 反向迭代器,rend在begin位置,其++和–操作与begin和end操作移动相反 |
| crbegin() | 不能修改内部键对值的反向迭代器 |
| crend() | 不能修内部键对值改的反向迭代器 |
注:这里就不演示迭代器了,与前面的序列式容器使用方法一样
| 函数声明 | 功能说明 |
|---|---|
| bool empty ( ) const | 判断map是否为空,是返回true,反之false |
| size_type size() const | 返回map中有效数据的个数 |
| mapped_type& operator[] (constkey_type& k) | 返回成员类型 mapped_type ,是容器中映射值的类型,在 map 中定义为其第二个模板参数 (T) 的别名 |
问题:当key不在map中时,通过operator获取对应value时会发生什么问题?

例子:
void Testmap1()
{
string Fruit[]{ "苹果", "雪梨", "栗子", "香蕉", "苹果", "苹果", "雪梨", "苹果", "栗子" };
map<string, int> CountF;
for (const auto& e : Fruit)
{
//auto ret = CountF.insert(make_pair(e, 1));
//map::iterator It = CountF.begin();
如果ret的bool为false,说明遇到相同的key,让second自增
//if (ret.second == false) {
// ++ret.first->second; // 访问ret的iterator中的value且自增
//}
//++It;
++CountF[e]; // 如果e不存在则直接初始化(调用inset),已存在则跳过,直接返回iterator->second
}
Show(CountF);
}
void Testmap2()
{
map<string, string> dict;
// insert返回值为pair -- 第一个类型参数为map的迭代器,第二个为bool类型(判断是否存在(数据冗余),不存在为true,存在为false)
pair<map<string, string>::iterator, bool> ret1 = dict.insert(make_pair("left", "左边"));
auto ret2 = dict.insert(make_pair("right", "右边"));
// []底层为:auto ret = insert(make_pair(k, mapped_type())); -- return ret.first->second -- mapped_type(是map第二个模板参数(T))
dict["abandom"] = "放弃"; // 插入k + 修改v
dict["ability"] = "能力"; // 插入k + 修改v
dict["left"] = "左边,剩余"; // 查找k + 修改v
dict["operator"]; // 插入k, v默认为map第二个模板参数的默认构造(string为"")
Show(dict);
}

| 函数声明 | 功能说明 |
|---|---|
| pair | 在map中插入键值对x,注意x是一个键值对,返回值也是键值对:iterator代表新插入元素的位置,bool代表释放插入成功 |
| void erase ( iterator position ) | 删除position位置上的元素 |
| size_type erase ( constkey_type& x ) | 删除键值为x的元素,并且返回删除键对值的个数 |
| void erase ( iterator first,iterator last ) | 删除[first, last)区间中的元素 |
| void swap (map | 交换二个map中的键对值 |
| void clear ( ) | 清空map中的元素 |
| iterator find ( const key_type& x) | 在map中插入key为x的元素,找到返回该元素的位置的迭代器,否则返回end() |
| const_iterator find ( constkey_type& x ) const | 在map中插入key为x的元素,找到返回该元素的位置的const迭代器,否则返回cend() |
| size_type count ( constkey_type& x ) const | 返回key为x的键值在map中的个数,注意map中key是唯一的,因此该函数的返回值要么为0,要么为1,因此也可以用该函数来检测一个key是否在map中 |
void Testmap1()
{
// 键对值 -- key, value
map<string, string> dict;
dict.insert(pair<string, string>("left", "左边"));
// make_pair是函数模板,底层是返回一个pair的匿名函数 -- return pair(...)
dict.insert(make_pair("left", "左边"));
// insert接口返回一个pair类型,如果第一次插入key则bool为true,但是插入相同的key,bool为false
// first为iterator,second为bool
pair<map<string, string>::iterator, bool> ret1 = dict.insert(pair<string, string>("abandon", "放弃"));
auto ret2 = dict.insert(make_pair("ability", "能力")); // make_pair是一个函数模板,用来构造pair
Show(dict);
for (const auto& kv : dict) {
cout << kv.first << ": " << kv.second << endl;
}
}
概念:
注意:multimap和map的唯一不同就是:map中的key是唯一的,而multimap中key是可以重复的
multimap与set的不同是: