序列式容器与关联式容器
C++容器分为序列式容器和关联式容器,序列式容器比如:vector list deque 等,这些容器统称为序列式容器,因为其底层为线性序列的数据结构(顺序表),里面存储的是元素本身,这一点和关联式容器不同,关联式容器存储的是<key , value>结构的键值对,对数据的检索时比序列式容器效率更高。
什么是键值对
键值对是用来表示一一对应关系的一种结构,该结构中一般只包含两个成员变量key和value,key代表键值value表示与key对应的信息
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)
{}
};
first ---> key , second -->value
树形结构的关联式容器:根据应用的场景不同,STL总共实现了两种不同结构的关联式容器:树型结构和哈希结构,树型结构的关联式容器主要有4中,map set multimap multiset。这四种容器的共同特点是:使用红黑树作为底层结构,容器中的元素是一有序的序列
什么是map
1.map是关联式容器,它按照特定的次序(按照key来比较)存储由键值key和 只value组合的元素
2.在map中,键值key通常用于排序和唯一的标记元素,而值value中存储与此键值key关联的内容,键值key和value的类型可能奴同,并且map内部,key与value通过成员类型value_type绑定在一起,为其取别名为pair:
typedef pair value_type;
3.在内部,map元素总是按照键值key进行比较排序的。
4.map支持下标访问符,在[]中放入key,就可以找到与之key对应的value
5.map通常被实现为红黑树
map 和 set
map :存储元素的类型<key, value> , 要求key必须唯一
set:存储元素的类型<key> , 要求key必须唯一
multimap:存储元素的类型<key, value> , key可以重复
multiset:存储元素的类型<key> , key可以重复
底层数据结构都是相同的----红黑树,在存储元素时,默认会按照key升序的比较
set的特性:可以进行去重 + 排序
multiset的特性: 排序
map模板参数列表:
一般实例化时:Key T的类型,根据场景需要,可能还需要指定比较器的类型 ----- 比如:存储自定义类型的对象关于key的降序
#include <iostream>
using namespace std;
#include <map>
#include <string>
//插入
void test2()
{
pair<string,string> array[3];
array[0].first = "orgin";
array[0].second = "橙子";
array[1].first = "apple";
array[1].second = "苹果";
array[2].first = "banan";
array[2].second = "香蕉";
map<string,string> m(array,array+sizeof(array)/ sizeof(array[0]));
//m.insert("name","名字");
//调用pair构造函数创建一个匿名键值对象
m.insert(pair<string,string>("name","名字"));
m.insert(pair<string,string>("man","男"));
m.insert(pair<string,string>("names","名字s"));
//make_pair是一个全局函数,输入两个参数将这两个参数打包成一个键值对返回
m.insert(make_pair("who","shui"));
cout<<m.size()<<endl;
for(auto& e: m)
cout<<e.first<<"---"<<e.second<<endl;
//插入失败:key不能重复,而apple已经存在
m.insert(make_pair("apple","苹果"));
//通过key来获取与key对应的value
// 注意:
// 1.operator[]:底层调用insert,其具有插入元素的功能
// 2.operator[key]:返回对应的value,其具有查找的功能
// 原理:
// 首先 将 <key , T> 构造成一个键值对,先map中进行insert
// 如果key已经存在,插入失败,直接返回与key对应的value
// 如果key不存在,插入成功,直接返回默认的value
m.erase("apple");
m.erase(m.begin(),m.end());
}
int main()
{
map<string,string> m; // 构造一个空的map
pair<string,string> array[3];
array[0].first = "orgin";
array[0].second = "橙子";
array[1].first = "apple";
array[1].second = "苹果";
array[2].first = "banan";
array[2].second = "香蕉";
map<string,string> m2(array,array+sizeof(array)/ sizeof(array[0]));
for(auto& e : m2)
cout<<e.first<<"--------"<<e.second<<endl;
cout<<endl;
//采用迭代器遍历m2
auto it = m2.begin();
while(it!=m2.end())
{
cout<<it->first<<"----"<<it->second<<endl;
it++;
}
test2();
return 0;
}
map和multimap中的key是不能修改的,如果要修改,不能直接修改,可以将key删除然后重新插入
multimap与map的区别:key的唯一性,multimap中没有operator[]
set的重要功能:排序 + 去重
multiset没有去重的功能,接口基本上与set的接口相同。
实际上map、 multimap、 set 、multiset的基本使用都是相同的,只需要注意几点就ok
1.map中的元素是键值对
2.map中的key是唯一的,并且不能修改
3.默认按照小于的方式对key进行排序