关联式容器其实就是关联数组概念的推广,依据选定的排序准则,自动为其元素排序。通常关联式容器是由二叉树做出来的,每个元素都有一个父节点和两个子节点,左子树的所有元素都比自己小,右子树的所有元素都比自己大。关联式容器的差别在于元素的类型以及处理重复元素的方式。关联式容器有一个很大的优点就是提供了对元素的快速访问,但是却不能实现任意位置的操作。

一、set/multiset类模板

集合是一种随机存取的容器,能按顺序存储一组值,其关键词和数据文件时同一个值,集合对象可以使程序按照次序来存储一组数值,在一个集合中的元素既作为被存储的数据又作为数据的关键值。集合的本质就是一个有序的排列,集合声明在头文件< set>内,multiset与set除了set元素中的值必须具有唯一值,即不能包含重复的元素,但是multiset可以包含重复的元素外,其他完全一样,**set/multiset的迭代器是双向迭代器**,本文以set为例介绍其用法。set的声明格式如下:

template < class Key,class Traits=less< Key>,class Allocator< Key> >
class set;

其中参数Key是存储在集合中元素的类型,参数Traits用于实现集合内部排序的仿函数,默认为less< Key>,即升序,参数Allocator为内存配置器,负责内存的分配和销毁。

(1)构造函数

(1) explicit set(const Traits& _Comp);          
(2)explicit set(const Traits& _Comp,const Allocator& _All);
(3)set(const _set& _Right);
(4)tmplate< class InputIterator> set(InputIterator first,InputIterator last);
(5)tmplate< class InputIterator> set(InputIterator first,InputIterator last,const Traits& _Comp);
(6)tmplate< class InputIterator> set(InputIterator first,InputIterator last,const Traits& _Comp,const Allocator& _All);


上面第一种方法最简单,定义一个空对象(容器),参数包含了一个二元谓词(重载()运算符),用于容器的内部排序。第二种形式出包含一个谓词外,还加入了内存配置器参数。第三种形式用已有的set来初始化新的set,第四种形式用first和last指定范围来初始化新的set。第五种形式比第四种形式多了参数_Comp,从而可以自定义排序规则。第六种形式在第五种形式的基础上增加了内存配置器。

(2)容量、搜寻、统计函数

bool empty( )const;                            /* 判断set是否为空 */

size_type size( )const;                      /* 获取set的长度 */

size_type max_size( )const;             /* 获取set的最大长度 */

size_type count( const Key& _Key )const;   /* 获取元素_Key的个数*/

iterator find(const Key& _Key)const;/* 返回键值为_Key的元素的位置,类型为迭代器 */
const iterator lower_bound(const Key& _Key)const;/* 返回键值大于等于_Key的第一个元素的迭代器位置 */

const iterator upper_bound(const Key& _Key)const;/* 返回键值大于_Key的第一个元素的迭代器位置 */

pair<
 iterator,iterator>equal_range(const Key& _Key)const;/* 
函数返回类型为迭代器对(pair),该迭代器对的两个迭代器分别指向集合中元素键值大于等于_Key的第一个元素的迭代器位置(first)和集合中键值大于_Key的第一个元素的迭代器位置(second)
 */
/*例如:std::pair<std::set<int>::iterator,std::set<int>::iterator> p; */


(3)迭代器及赋值函数

void swap(set& str);/* 交换两set的元素 */
const_iterator begin();/* 返回set的首元素 */
const_iterator end();/* 返回set的尾元素 */
const_reverse_iterator rbegin();/* 返回set的尾元素 */
const_reverse_iterator rend();/* 返回set的首元素 */


(4)插入删除函数
不能对空集合进行删除操作,所以在删除函数前,需要有容器容量判断。

pair<iterator,bool>insert(const value_type& x);/* 返回值为pair类型的迭代器指针first代表插入元素的位置,第二个为bool类型,表示插入是否成功 */

iterator insert(iterator it,const value_type& x);/* 在集合it位置插入元素x,实际上不生效,会自动排序 */

void insert(const value_type& first,const value_type& last);/* 插入迭代器first到last之间的元素到集合中,打乱,重新排序 */

iterator erase(iterator it);/* 清除元素it */
iterator erase(iterator first,iterator last);/* 清除迭代器first到last之间的元素 */
size_type erase(const key& key);/* 清除关键值为key的元素 */

void clear();/* 清空set集合 */


(5)元素比较函数

key_compare key_comp()const;           /* 返回该set的键值比较函数 */
value_compare value_comp()const;    /* 返回该set的实值比较函数 */

二、map/multimap类模板

容器map是键-值对的集合,键是独一无二的,可使用键作为下标获取对应的值,map/maomultimap容器的对象以数据的形式存放在二叉树中,容器map与multimap基本是一样的,除了multimap允许重复元素,map不允许外,**map/multimap的迭代器是双向迭代器**,下面以map为例,详细讲解该模板的使用。
map声明在< map>内,模板为:

template< class Key,class T,class Compare=less< Key>,class Allocator=allocator<pair< const key,T>>>
class map;

第一个参数为容器的key,第二个template参数当做元素的value。第三个参数可有可无,用于定义排序规则,仅由key决定,默认为less< Key>。

(1)map/multimap的构造函数

map<key,value> c;/* 定义一个空的map容器*/
map<key,value,greater< int>> c;/* 定义一个空的map容器,使用仿函数greater进行排序*/
map<key,value> c(first,last);/* 定义一个map容器并用first到last的元素去初始化*/


(2)容量函数

bool empty( )const;                            /* 判断map是否为空 */

size_type size( )const;                      /* 获取map的长度 */

size_type max_size( )const;             /* 获取map的最大长度 */

(3)迭代器函数

iterator begin();/* 返回map的首元素 */
const_iterator begin();/* 返回map的首元素 */

iterator end();/* 返回map的尾元素 */
const_iterator end();/* 返回map的尾元素 */

reverse_iterator rbegin();/* 返回map的尾元素 */
const_reverse_iterator rbegin();/* 返回map的尾元素 */

reverse_iterator rbegin();/* 返回map的尾元素 */
const_reverse_iterator rend();/* 返回map的首元素 */

(4)交换函数

void swap(set& str);/* 交换两map的元素 */

(5)插入和删除函数

pair<iterator,bool>insert(const value_type& x);/* 返回值为pair类型的迭代器指针first代表插入元素的位置,第二个为bool类型,表示插入是否成功 */

iterator insert(iterator it,const value_type& x);/* 在集合it位置插入元素x。自动排序,不起作用 */

void insert(const value_type& first,const value_type& last);/* 插入迭代器first到last之间的元素到集合中 */

iterator erase(iterator it);/* 清除元素it */
iterator erase(iterator first,iterator last);/* 清除迭代器first到last之间的元素 */
size_type erase(const key& key);/* 清除关键值为key的元素 */

void clear()const; /* 清空map元素,等同于erase(map::begin(),map::end()) */

map插入元素的四种方法:
方法一:例:
map<int, string> mp;
mp.insert(pair<int,string>(1,"aaaaa"));
 
方法二:例:
map<int, string> mp;
mp.insert(make_pair<int,string>(2,"bbbbb"));
 
方法三:例:
map<int, string> mp;
mp.insert(map<int, string>::value_type(3,"ccccc"));
 
方法四:例:
map<int, string> mp;
mp[4] = "ddddd";
 
四种方法异同:
前三种方法当出现重复键时,编译器会报错,而第四种方法,当键重复时,会覆盖掉之前的键值对。

(6)容量、搜寻、统计函数

size_type count( const Key& _Key )const;   /* 获取元素_Key的个数*/

iterator find(const Key& _Key)const;
const_iterator find(const Key& _Key)const;
/* 返回键值为_Key的元素的位置,类型为迭代器,未找到返回end() */

const iterator lower_bound(const Key& _Key)const;/* 返回键值大于_Key前面的那个元素或等于_Key的位置类型为迭代器 */

const iterator upper_bound(const Key& _Key)const;/* 返回键值大于_Key的元素的迭代器位置 */

pair<
 iterator,iterator>equal_range(const Key& _Key)const;/* 
函数返回类型为迭代器对(pair),该迭代器对的两个迭代器分别指向集合中元素键值大于_Key前面的那个元素或等于_Key的位置(first)和集合中键值大于参数_Key的第一个元素(second)
 */


(7)元素比较函数

key_compare key_comp()const;           /* 键值比较函数 */
value_compare value_comp()const;    /* 实值比较函数 */

例如以下代码返回值为 1,即第一个元素键值小于第二个元素的键值:

#include "stdafx.h"
#include <iostream>
#include <algorithm>
#include <map>
int main()
{
    std::map<int,double> mymap;
    mymap.insert(std::pair<int,double>(1,1.1));
    mymap.insert(std::pair<int,double>(2,2.1));
    
    std::map<int,double>::key_compare kc = mymap.key_comp();
    std::cout<<std::endl;
    std::cout<<kc(1,2)<<std::endl;
    
    std::cin.get();
    return 0;
}

(8)获取内存分配器

Allocator get_allocator(void);/* 获取集合的内存配置器首地址 */