map属于STL中的关联式容器,它所有的元素都是pair,同时拥有实值(value)和键值(key)。有没有感觉像hash,也是成对存在的。没错在STL中还有一种关联式容器叫hash_map,底层当然不用怀疑是用hashtable支持的。而map的底层是rbtree。
看到rbtree你肯定就不难理解map所有的元素都会根据元素的键值自动被排序了吧。和set一样,map也不允许两个元素拥有相同的键值。几乎所有的map操作也都转调用rbtree的接口操作 。
map的迭代器问题,和list相似。对map进行插入删除操作,除被删除元素的迭代器失效后其他的操作之前的迭代器都依然有效(包括指针,引用)。那么通过迭代器修改元素的键值可以吗?通过迭代器修改元素的实值可以吗?答案是前者不可以,后者可以。因为map的内部是通过元素的键值进行排序的,修改元素的键值当然会破坏map的结构组织,所以不可通过元素的迭代器修改元素的键值。
来看看map是怎么同时保存一对值的。
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){}
};
看完pair的结构体定义,你应该就知道了吧,map是通过pair把元素的键值和元素的实值绑定到一块,然后再添加到map中。
来看看map的构造函数:
map(); // 默认构造函数
map(const map& m) // 拷贝构造函数
map(iterator begin, iterator end ); //区间构造函数
map(iterator begin, iterator end, const traits& _compare) //带比较谓词的构造函数
map(iterator begin, iterator end, const traits& _compare, const allocator& all) //带分配器
测试代码如下:
#include <iostream>
using namespace std;
#include <map>
void main()
{
map<int, int> map1;
map1.insert(pair<int, int>(1, 10));
map1.insert(pair<int, int>(2, 20));
map1.insert(pair<int, int>(2, 30)); //键值重复则添加不进去
map1[3] = 30;
map1[4] = 40;
map1[6] = 60;
map<int, int> map2(map1);
map<int, int>::iterator it = map1.begin();
map<int, int>::iterator it2 = map1.end();
map<int, int> map3(it, it2);
//map(iterator begin, iterator end, const traits& _compare) //带比较谓词的构造函数
//map(iterator begin, iterator end, const traits& _compare, const allocator& all) //带分配器
for (; it != it2; it++)
{
cout << it->first << " " << it->second << endl;
}
pair<int, int> val(5, 50);
map<int, int>::iterator temp;
temp = map1.insert(val).first; //insert返回型别为pair。
cout << (*temp).second << endl;
//bool a = map1.insert(val).second;
//bool flg = map1.insert(pair<int,int>(7,70)).second;
cout << "---------------------------------------" << endl;
cout << map1.count(2) << endl; //返回指定元素出现的次数,传入的是键值,结果非0即1
cout << "map1.size() = " << map1.size() << endl;
//关键字为1、2、3、4、5、6 以下为三种删除
map<int, int>::iterator it3 = map1.begin();
map1.erase(it3);
it = map1.begin();
it2 = ++it;
--it;
map1.erase(it, it2); //删除区间[it-it2),注意是前闭后开
map1.erase(5); //剩余关键字3、4、6
cout << "map1.size() = " << map1.size() << endl;
cout << "map1.max_size() = " << map1.max_size() << endl; //178956970
//map1.clear();
if (map1.empty())
{
cout << "map1 is empty" << endl;
}
else
cout << "map1 is not empty" << endl;
//rbegin() 返回一个指向map尾部的逆向迭代器
//rend() 返回一个指向map头部的逆向迭代器
map<int, int>::reverse_iterator it4 = map2.rbegin();
for (; it4 != map2.rend(); it4++)
{
cout << it4->first << " " << it4->second << endl;
}
//对于关联式容器使用其提供的find函数搜索元素比使用stl算法find()更有效率
map<int, int>::iterator it5;
it5 = map2.find(2);
if (it5 == map2.end())
{
cout << "关键字为2的元素在map2中未找到\n";
}
else
{
cout << "关键字为2的元素在map2中成功找到\n";
}
it5->second = 100;
cout << "通过迭代器修改后值为 :" << it5->second << endl;
//it5->first = 12;
}
运行结果:
通过map的迭代器修改其键值是编译不过的,但可以通过它的迭代器修改它的实值。
下面测试以下方法:
//lower_bound() 返回键值 >= 给定元素的第一个位置
//upper_bound() 返回键值>给定元素的第一个位置
//swap() 交换两个map
#include <iostream>
using namespace std;
#include <map>
void main()
{
map<int, int> map1;
for (int i = 1; i <= 10; i++)
{
map1[i] = i * 10;
}
cout << map1.lower_bound(5)->first<< endl;
cout << map1.lower_bound(5)->second << endl;
cout << map1.upper_bound(5)->first << endl;
cout << map1.upper_bound(5)->second << endl;
map<int, int> map2;
map2.insert(pair<int, int>(1, 11));
map2.insert(pair<int, int>(2, 22));
map2.insert(pair<int, int>(3, 33));
cout << "交换前----------------" << endl;
cout << "map1.size() = " << map1.size() << endl;
cout << "map2.size() = " << map2.size() << endl;
map1.swap(map2); //交换两个map,两map的键值和实值类型必须都相同
cout << "交换后----------------" << endl;
cout << "map1.size() = " << map1.size() << endl;
cout << "map2.size() = " << map2.size() << endl;
}
测试结果:
结束~~