std::map的使用
// std::map 的定义
template<class _Kty, // Key class _Ty, // Value class _Pr = less<_Kty>, // 比较器 class _Alloc = allocator<pair<const _Kty, _Ty> > > // 内存分配器 class map : public _Tree<_Tmap_traits<_Kty, _Ty, _Pr, _Alloc, false> > // 父类(红黑树) { ...... }
// std::map的默认比较器
// 要实现Key的 "<" 操作符
template<class _Ty> struct less : public binary_function<_Ty, _Ty, bool> { // functor for operator< bool operator()(const _Ty& _Left, const _Ty& _Right) const { // apply operator< to operands return (_Left < _Right); } }; // std::map的默认比较器的父类(其实里面没有东西) // TEMPLATE STRUCT binary_function template<class _Arg1, class _Arg2, class _Result> struct binary_function { // base class for binary functions typedef _Arg1 first_argument_type; typedef _Arg2 second_argument_type; typedef _Result result_type; };
可以看到, 默认比较器使用了Key的"<"操作符, 使得std::map中的Key能排序.
有一个问题就是, 如果Key是指针, 默认的比较器中的"<"操作符就只是指针数值的比较; 此时就需要自定义比较器来使得Key能正确排序.
或者说, 你的Key的排序算法与"<"操作符不一样, 你也需要自定义比较器.
// 看如下代码(VC2010)
#include "stdafx.h" #include <string> #include <map> // 定义自己std::map比较器 typedef std::string* PSTDString; struct PStringLess { // functor for operator< bool operator()(const PSTDString& pStrLeft, const PSTDString& pStrRight) const { // apply operator< to operands return (*pStrLeft) < (*pStrRight); } }; template<class _Ty> struct PLess { // functor for operator< bool operator()(const _Ty& pLeft, const _Ty& pRight) const { // apply operator< to operands return (*pLeft) < (*pRight); // 这个比较器与默认比较器不同的地方 } }; int _tmain(int argc, _TCHAR* argv[]) { // 这里使用std::map的默认比较器. // std::map的默认比较器调用了Key的"<"操作符 // (这里是std::string的"<"操作符) std::map<std::string, int> StringToIntMap; // 这里Key是std::string*, 默认比较器使用的是指针的"<"操作符 // (就是简单的指针数值比较) std::map<std::string*, int> PStringToIntMap; // 如果Key是一个指针, 为了正确排序, 需要自己定义比较器对象 std::map<PSTDString, int, PStringLess> PStringToIntMap1; std::string str1 = "1"; std::string str2 = "2"; std::string str3 = "3"; PStringToIntMap1[&str1] = 3; PStringToIntMap1[&str2] = 2; PStringToIntMap1[&str3] = 1; // 这个使用更通用的比较器 std::map<PSTDString, int, PLess<PSTDString> > PStringToIntMap2; PStringToIntMap2[&str1] = 3; PStringToIntMap2[&str2] = 2; PStringToIntMap2[&str3] = 1; return 0; }
看2.1中的代码
// 定义自己std::map比较器
// 定义自己std::map比较器 typedef std::string* PSTDString; struct PStringLess { // functor for operator< bool operator()(const PSTDString& pStrLeft, const PSTDString& pStrRight) const { // apply operator< to operands return (*pStrLeft) < (*pStrRight); } };
// 更通用的指针Key比较器
template<class _Ty> struct PLess { // functor for operator< bool operator()(const _Ty& pLeft, const _Ty& pRight) const { // apply operator< to operands return (*pLeft) < (*pRight); // 这个比较器与默认比较器不同的地方 } };
使用map::lower_bound和map::upper_bound得到最接近的Key, 注意这两个方法的区别:
std::map<double, int> mmm; mmm[1.5] = 15; mmm[2.5] = 25; mmm[3.5] = 35; mmm[4.5] = 45; mmm[7.5] = 75; mmm[5.5] = 55; mmm[9.5] = 95; mmm[2.3] = 23; mmm[23.5] = 235; std::map<double, int>::iterator iter1 = mmm.lower_bound(3.3); // 得到mmm[3.5] = 35; std::map<double, int>::iterator iter2 = mmm.lower_bound(3.5); // 得到mmm[3.5] = 35; std::map<double, int>::iterator iter3 = mmm.upper_bound(3.3); // 得到mmm[3.5] = 35; std::map<double, int>::iterator iter4 = mmm.upper_bound(3.5); // 得到mmm[4.5] = 45;