Map和Set 所谓 关联容器 Associative Container 与顺序容器(Sequential Container)的本质区别在于:
关联容器是通过键(key)存储和读取元素的,而顺序容器则通过元素在容器中的位置顺序存储和访问元素。
map的元素是“键-值”对的二元组形式:键用作元素在map中的索引,而值 则表示所存储和读取的数据。
set的元素包含一个键,并有效地支持关于某个键是否存在的查询。
map 关联数组:元素通过键来存储和读取
set 大小可变的集合,支持通过键实现的快速读取
multimap 支持同一个键多次出现的map类型
multiset 支持同一个键多次出现的set类型
set和multiset容器的能力
set和multiset容器的内部结构通常由平衡二叉树(balanced binary tree)来实现。当元素放入容器中时,会按照一定的排序法则自动排序,默认是按照less<>排序规则来排序。这种自动排序的特性加速了元素查找的过程,但是也带来了一个问题:不可以直接修改set或multiset容器中的元素值,因为这样做就可能违反了元素自动排序的规则。如果你希望修改一个元素的值,必须先删除原有的元素,再插入新的元素。
查找元素
在map和set容器中,元素是有序存储的(升序),同样multimap和multiset也一样。因此,在multimap和multiset容器中,如果某个键对应多个实例,则这些实例在容器中将相邻存放,即迭代遍历时,可保证依次返回特定键所关联的所有元素。
要查找特定键所有相关联的值,可以有下面三种方法:
1)配合使用find和count来查找:count函数求出某键出现的次数,而find操作返回指向第一个键的实例的迭代器。
2)使用lower_bound和upper_bound函数:这两个函数常用于multimap和multiset,但也可以用于map和set容器。所有这些操作都需要传递一个键,并返回一个迭代器。
m.lower_bound(k) 返回一个迭代器,指向键不小于k的第一个元素
m.upper_bound(k) 返回一个迭代器,指向键大于k的第一个元素
m.equal_range(k) 返回一个迭代器的pair对象
它的first成员等价于m.lower_bound(k),而second成员则等价于m.upper_bound(k)
注意:形成的有效区间是[lower_bound(k), upper_bound(i)),是个半开半闭区间。
//测试 Map容器
void TestMap()
{
typedef map<int, string> UDT_MAP_INT_CSTRING; //定义类型
map<int,string> M;
M[1] = "One";//该插入方法效率不高
M.insert(map<int, string> :: value_type(2, "Two"));//建议使用该插入方法
M.insert(make_pair(11,"A"));
int nFindKey = 2; //要查找的Key
UDT_MAP_INT_CSTRING::iterator pItFind = M.find(nFindKey);
if (pItFind == M.end())
{
cout << "not found" << endl;
}
else
{
if (pItFind->first)//first对应key, second对应value
cout << pItFind->second.c_str() << endl;
}
for(map<int,string>::iterator pIt=M.begin(); pIt!=M.end(); pIt++)
{
if (pIt->first)
cout << pIt->second.c_str();
}
cout << endl;
M.erase(1);//删除key为1的元素
for(map<int,string>::iterator pIt=M.begin(); pIt!=M.end(); pIt++)
{
if (pIt->first)
cout << pIt->second.c_str();
}
cout << endl;
M.erase(pItFind);//删除迭代器指向的元素
for(map<int,string>::iterator pIt=M.begin(); pIt!=M.end(); pIt++)
{
if (pIt->first)
cout << pIt->second.c_str();
}
cout << endl;
}
Output:
Two
OneTwoA
TwoA
A
//测试 Multiset容器
void TestMultiset()
{
cout << "TestMultiset" << endl;
const int N = 5;
int a[N] = {4,1,1,3,5};
multiset<int> A(a,a+N);//使用数组初始化容器,multiset容器 升序排序
copy(A.begin(),A.end(),ostream_iterator<int>(cout," "));
cout << endl;
}
Output:
TestMultiset
1 1 3 4 5
//测试 Multiset容器
void TestMultiset2()
{
cout << "TestMultiset" << endl;
multiset <int>::iterator ms1_Iter, ms2_Iter, ms3_Iter;
multiset <int>::iterator ms4_Iter, ms5_Iter, ms6_Iter;
// Create an empty multiset ms0 of key type integer
multiset <int> ms0;
// Create an empty multiset ms1 with the key comparison
// function of less than, then insert 4 elements
multiset <int, less<int> > ms1; //升序存储
ms1.insert( 10 );
ms1.insert( 20 );
ms1.insert( 20 );
ms1.insert( 40 );
ms1.insert( 4 );
// Create an empty multiset ms2 with the key comparison
// function of geater than, then insert 2 elements
multiset <int, greater<int> > ms2;//降序存储
ms2.insert( 10 );
ms2.insert( 20 );
ms2.insert( 2 );
// Create a multiset ms3 with the
// allocator of multiset ms1
multiset <int>::allocator_type ms1_Alloc;
ms1_Alloc = ms1.get_allocator( );
multiset <int> ms3( less<int>(), ms1_Alloc );
ms3.insert( 30 );
// Create a copy, multiset ms4, of multiset ms1
multiset <int> ms4( ms1 );
// Create a multiset ms5 by copying the range ms1[_First, _Last)
multiset <int>::const_iterator ms1_bcIter, ms1_ecIter;
ms1_bcIter = ms1.begin( );
ms1_ecIter = ms1.begin( );
ms1_ecIter++;
ms1_ecIter++;
multiset <int> ms5( ms1_bcIter, ms1_ecIter );
// Create a multiset ms6 by copying the range ms4[_First, _Last)
// and with the allocator of multiset ms2
multiset <int>::allocator_type ms2_Alloc;
ms2_Alloc = ms2.get_allocator( );
multiset <int> ms6( ms4.begin( ), ++ms4.begin( ), less<int>( ), ms2_Alloc );
cout << "ms1 =";
for ( ms1_Iter = ms1.begin( ); ms1_Iter != ms1.end( ); ms1_Iter++ )
cout << " " << *ms1_Iter;
cout << endl;
//当multiset容器降序 ms2_Iter=ms2.begin();报错
cout << "ms2 = " << *ms2.begin( ) << " " << *++ms2.begin( )
<< endl;
cout << "ms3 =";
for ( ms3_Iter = ms3.begin( ); ms3_Iter != ms3.end( ); ms3_Iter++ )
cout << " " << *ms3_Iter;
cout << endl;
cout << "ms4 =";
for ( ms4_Iter = ms4.begin( ); ms4_Iter != ms4.end( ); ms4_Iter++ )
cout << " " << *ms4_Iter;
cout << endl;
cout << "ms5 =";
for ( ms5_Iter = ms5.begin( ); ms5_Iter != ms5.end( ); ms5_Iter++ )
cout << " " << *ms5_Iter;
cout << endl;
cout << "ms6 =";
for ( ms6_Iter = ms6.begin( ); ms6_Iter != ms6.end( ); ms6_Iter++ )
cout << " " << *ms6_Iter;
cout << endl;
}
Output:
TestMultiset
ms1 = 4 10 20 20 40
ms2 = 20 10
ms3 = 30
ms4 = 4 10 20 20 40
ms5 = 4 10
ms6 = 4