【1】map容器
map 是关联容器。容器中的每一个元素都是由一个键值和一个数据值组成的。
set 是一个集合它以其元素作为键值(同一个键值只能出现一次),且默认以升序排列。
list 是一个顺序容器。
【2】map容器使用方法以及实例
(1)定义、插入数据方法实例
1 // map容器定义、插入数据方式代码 2 #include
分析总结:
以上四种用法,虽然都可以实现数据的插入,但是它们是有区别的。
当然,第一、二、三种在效果上是完全一样的,用insert函数插入数据,在数据的插入过程中涉及到集合的唯一性这个概念:
即当map中有这个关键字时,insert操作再插入数据是不会成功的。
但是,用数组(第四种)方式就不同了,它可以覆盖以前该关键字对应的值,用程序说明如下:
mapStu1.insert(map<int, string>::value_type(2, "Sun"));
mapStu1.insert(map<int, string>::value_type(2, "Zhao"));
上面这两条语句执行后,mapStu1中2这个关键字对应的值是“Sun”,第二条语句并没有生效。
那么,这就涉及到我们怎么知道insert语句是否插入成功的问题?可以用pair来获得是否插入成功,程序如下:
pair<map<int, string>::iterator, bool> iter_pair;
iter_pair = mapStu1.insert(map<int, string>::value_type(3, "Li"));
我们通过pair的第二个变量来判断是否插入成功,它的第一个变量返回的是一个map的迭代器,
如果插入成功的话迭代器的变量iter_pair.second应该是true,否则为false。
(2)遍历map容器的三种方式
程序代码如下:
1 #include2 #include 3 #include 4 using namespace std; 5 6 // 第一种方式 7 void print1(map & mapStu) 8 { 9 cout << "第一种遍历方式:" << endl;10 cout << "size: " << mapStu.size() << endl;11 // 迭代map容器中的数据12 map ::iterator iter = mapStu.begin();13 for (; iter != mapStu.end(); ++iter)14 {15 cout << "key: " << iter->first << " value: " << iter->second << endl;16 }17 cout << endl;18 }19 20 // 第二种方式21 void print2(map & mapStu)22 {23 cout << "第二种遍历方式:" << endl;24 cout << "size: " << mapStu.size() << endl;25 // 迭代map容器中的数据26 map ::reverse_iterator iter = mapStu.rbegin();27 for (; iter != mapStu.rend(); ++iter)28 {29 cout << "key: " << iter->first << " value: " << iter->second << endl;30 }31 32 cout << endl;33 }34 35 // 第三种方式36 void print3(map & mapStu)37 {38 cout << "第三种遍历方式:" << endl;39 int nSize = mapStu.size();40 cout << "size: " << mapStu.size() << endl;41 // 迭代map容器中的数据42 for(int nIndex = 1; nIndex < nSize + 1; ++nIndex)43 {44 cout << "<" << nIndex << " :: " << mapStu[nIndex] << ">" << endl;45 }46 }47 48 void main()49 {50 typedef map mapType;51 mapType mapStu;52 53 // 用insert函数插入value_type数据54 mapStu.insert(map ::value_type(1, "Qin"));55 mapStu.insert(map ::value_type(2, "Sun"));56 mapStu.insert(map ::value_type(3, "Wang"));57 mapStu.insert(map ::value_type(4, "Zhao"));58 print1(mapStu); // 第一种方式59 print2(mapStu); // 第二种方式60 print3(mapStu); // 第三种方式61 62 system("pause");63 }64 // run out:65 /*66 第一种遍历方式:67 size: 468 key: 1 value: Qin69 key: 2 value: Sun70 key: 3 value: Wang71 key: 4 value: Zhao72 73 第二种遍历方式:74 size: 475 key: 4 value: Zhao76 key: 3 value: Wang77 key: 2 value: Sun78 key: 1 value: Qin79 80 第三种遍历方式:81 size: 482 <1 :: Qin>83 <2 :: Sun>84 <3 :: Wang>85 <4 :: Zhao>86 请按任意键继续. . .87 */
(3)查找数据的三种方式
应用实例代码如下:
1 // 三种查找数据的方式 2 #include3 #include 4 #include 5 using namespace std; 6 7 // 第一种方式 8 void print1(map & mapStu) 9 { 10 cout << "遍历容器数据:" << endl; 11 cout << "size: " << mapStu.size() << endl; 12 // 迭代map容器中的数据 13 map ::iterator iter = mapStu.begin(); 14 for (; iter != mapStu.end(); ++iter) 15 { 16 cout << "key: " << iter->first << " value: " << iter->second << endl; 17 } 18 } 19 20 void main() 21 { 22 typedef map mapType; 23 mapType mapStu; 24 25 // 用insert函数插入value_type数据 26 mapStu.insert(map ::value_type(1, "Qin")); 27 mapStu.insert(map ::value_type(2, "Sun")); 28 mapStu.insert(map ::value_type(3, "Wang")); 29 mapStu.insert(map ::value_type(4, "Zhao")); 30 // 第一种查找数据方式 31 // count函数求的是关键字key的个数?key是不能重复的,所以返回只有0和1两种结果。 32 cout << "查找关键字3的结果 : " << mapStu.count(1) << endl; 33 cout << "查找关键字5的结果: " << mapStu.count(5) << endl; 34 // 第二种查找数据方式 35 map ::iterator iter; 36 iter = mapStu.find(1); 37 if (iter != mapStu.end()) 38 { 39 cout << "Find, the value is " << iter->second << endl; 40 } 41 else 42 { 43 cout << "Do not Find !" << endl; 44 } 45 // 第三种查找数据方式 46 print1(mapStu); 47 iter = mapStu.lower_bound(2); 48 { 49 cout << "lower_bound(2) :: (不小于2) " << iter->second << endl; 50 } 51 52 iter = mapStu.lower_bound(3); 53 { 54 cout << "lower_bound(3) :: (不小于3) " << iter->second << endl; 55 } 56 57 iter = mapStu.upper_bound(2); 58 { 59 cout << "upper_bound(2) :: (大于2) " << iter->second << endl; 60 } 61 62 iter = mapStu.upper_bound(3); 63 { 64 cout << "upper_bound(3) :: (大于3) " << iter->second << endl; 65 } 66 67 pair ::iterator, map ::iterator> mapPair; 68 mapPair = mapStu.equal_range(2); 69 if (mapPair.first == mapPair.second) 70 { 71 cout << "equal_range(2) :: Do not Find!" << endl; 72 } 73 else 74 { 75 cout << "equal_range(2) :: Find!" << endl; 76 } 77 78 mapPair = mapStu.equal_range(5); 79 if (mapPair.first == mapPair.second) 80 { 81 cout << "equal_range(5) :: Do not Find!" << endl; 82 } 83 else 84 { 85 cout << "equal_range(5) :: Find!" << endl; 86 } 87 88 system("pause"); 89 } 90 // run out: 91 /* 92 查找关键字3的结果 : 1 93 查找关键字5的结果: 0 94 Find, the value is Qin 95 遍历容器数据: 96 size: 4 97 key: 1 value: Qin 98 key: 2 value: Sun 99 key: 3 value: Wang100 key: 4 value: Zhao101 lower_bound(2) :: (不小于2) Sun102 lower_bound(3) :: (不小于3) Wang103 upper_bound(2) :: (大于2) Wang104 upper_bound(3) :: (大于3) Zhao105 equal_range(2) :: Find!106 equal_range(5) :: Do not Find!107 请按任意键继续. . .108 */
注意:
lower_bound(x)不是下界,而是大于等于x的最小值。
upper_bound(x) 大于x的最小值。
(4)查询、修改、删除、大小、比较、清空、判空等等方法。
应用实例代码如下:
1 #include2 #include 3 #include 4 using namespace std; 5 6 // 打印map容器数据 7 void print(map & mapStu) 8 { 9 cout << "size: " << mapStu.size() << endl; 10 // 迭代map容器中的数据 11 map ::iterator iter = mapStu.begin(); 12 for (; iter != mapStu.end(); ++iter) 13 { 14 cout << "key: " << iter->first << " value: " << iter->second << endl; 15 } 16 cout << endl; 17 } 18 19 void main() 20 { 21 typedef map mapType; 22 mapType mapStu1; 23 24 // 用insert函数插入value_type数据 25 mapStu1.insert(map ::value_type(1, "Qin")); 26 mapStu1.insert(map ::value_type(2, "Sun")); 27 mapStu1.insert(map ::value_type(3, "Wang")); 28 mapStu1.insert(map ::value_type(2, "Zhao")); 29 print(mapStu1); 30 // 查找数据的两种方式: 31 // 方式1: 32 string str2 = mapStu1[2]; 33 cout << str2 << endl; 34 // 方式2: 35 mapType::iterator my_Iter; 36 my_Iter = mapStu1.find(3); 37 string str3 = my_Iter->second; 38 cout << str3 << endl << endl; 39 // 修改数据的两种方式: 40 // 方式1: 41 mapStu1[2] = "Ma"; 42 // 方式2: 43 my_Iter->second = "Yuan"; 44 print(mapStu1); 45 // size 函数 和 empty函数 46 cout << "size() :: " << mapStu1.size() << endl; 47 cout << "empty() :: " << mapStu1.empty() << endl; 48 mapStu1.clear(); 49 cout << "size() :: " << mapStu1.size() << endl; 50 cout << "empty() :: " << mapStu1.empty() << endl; 51 // 比较 ==、>=、<=、!= 52 mapType mapStu2; 53 cout << "mapStu1 == mapStu2 :: " << (mapStu1 == mapStu2) << endl; 54 cout << "mapStu1 >= mapStu2 :: " << (mapStu1 >= mapStu2) << endl; 55 cout << "mapStu1 <= mapStu2 :: " << (mapStu1 <= mapStu2) << endl; 56 cout << "mapStu1 != mapStu2 :: " << (mapStu1 != mapStu2) << endl << endl; 57 58 mapStu1.insert(map ::value_type(1, "Qin")); 59 mapStu1.insert(map ::value_type(2, "Sun")); 60 mapStu1.insert(map ::value_type(3, "Wang")); 61 mapStu1.insert(map ::value_type(4, "Qiang")); 62 mapStu1.insert(map ::value_type(5, "Huang")); 63 mapStu1.insert(map ::value_type(6, "Li")); 64 mapStu1.insert(map ::value_type(7, "Hou")); 65 mapStu1.insert(map ::value_type(8, "Lin")); 66 mapStu1.insert(map ::value_type(9, "Li")); 67 68 // 删除操作 69 cout << "删除前打印数据信息:" << endl; 70 print(mapStu1); 71 mapType::iterator iter; 72 // 第一种删除(代码1) 73 for (iter = mapStu1.begin(); iter != mapStu1.end();) 74 { 75 if (5 == iter->first) 76 { 77 iter = mapStu1.erase(iter); 78 } 79 else 80 { 81 ++iter; 82 } 83 } 84 85 // 第一种删除(代码2)(注意代码层面的差异) 86 for (iter = mapStu1.begin(); iter != mapStu1.end();) 87 { 88 if ("Li" == iter->second) 89 { 90 mapStu1.erase(iter++); 91 } 92 else 93 { 94 ++iter; 95 } 96 } 97 cout << "删除关键字5 以及 值“Li”后: " << endl; 98 print(mapStu1); 99 100 // 第一种删除(代码3)(注意代码层面的差异)101 my_Iter = mapStu1.find(2);102 mapStu1.erase(my_Iter);103 cout << "删除关键字2后: " << endl;104 print(mapStu1);105 106 // 第二种删除(直接删除关键字)107 int nResult = mapStu1.erase(3); // 如果删除了会返回1,否则返回0108 cout << nResult << endl;109 cout << "删除关键字3后: " << endl;110 print(mapStu1);111 112 // 第三种删除(用迭代器,成片的删除)113 mapStu1.erase(++mapStu1.begin(), mapStu1.end());114 cout << "剩第一位,其它全部删除后: " << endl;115 print(mapStu1);116 117 system("pause");118 }119 120 // run out:121 /*122 size: 3123 key: 1 value: Qin124 key: 2 value: Sun125 key: 3 value: Wang126 127 Sun128 Wang129 130 size: 3131 key: 1 value: Qin132 key: 2 value: Ma133 key: 3 value: Yuan134 135 size() :: 3136 empty() :: 0137 size() :: 0138 empty() :: 1139 mapStu1 == mapStu2 :: 1140 mapStu1 >= mapStu2 :: 1141 mapStu1 <= mapStu2 :: 1142 mapStu1 != mapStu2 :: 0143 144 删除前打印数据信息:145 size: 9146 key: 1 value: Qin147 key: 2 value: Sun148 key: 3 value: Wang149 key: 4 value: Qiang150 key: 5 value: Huang151 key: 6 value: Li152 key: 7 value: Hou153 key: 8 value: Lin154 key: 9 value: Li155 156 删除关键字5 以及 值“Li”后:157 size: 6158 key: 1 value: Qin159 key: 2 value: Sun160 key: 3 value: Wang161 key: 4 value: Qiang162 key: 7 value: Hou163 key: 8 value: Lin164 165 删除关键字2后:166 size: 5167 key: 1 value: Qin168 key: 3 value: Wang169 key: 4 value: Qiang170 key: 7 value: Hou171 key: 8 value: Lin172 173 1174 删除关键字3后:175 size: 4176 key: 1 value: Qin177 key: 4 value: Qiang178 key: 7 value: Hou179 key: 8 value: Lin180 181 剩第一位,其它全部删除后:182 size: 1183 key: 1 value: Qin184 185 请按任意键继续. . .186 */
(5)map 容器排序问题
请看下面一段代码:
1 #include2 #include 3 using namespace std; 4 5 typedef struct tagStudentInfo 6 { 7 int nID; 8 string strName; 9 } StudentInfo, *PStudentInfo; // 学生信息10 11 void main()12 {13 // 用学生信息映射分数14 map mapStudent;15 StudentInfo studentInfo;16 studentInfo.nID = 1;17 studentInfo.strName = "student_one";18 mapStudent.insert(pair (studentInfo, 90));19 studentInfo.nID = 2;20 studentInfo.strName = "student_two";21 mapStudent.insert(pair (studentInfo, 80));22 }
注意:以上程序编译无法通过!
由编译器错误提示分析:排序问题!STL中默认是采用小于号来排序的,当关键字是一个结构体时,涉及到排序就会出现问题。
因为它没有小于号操作,insert等函数在编译的时候过不去,下面给出两个方法解决这个问题:
1、解决方法1,重载运算符。
1 // 解决方法1 2 3 #include4 #include 5 using namespace std; 6 7 typedef struct tagStudentInfo 8 { 9 int nID;10 string strName;11 12 bool operator < (tagStudentInfo const & _A)const13 {14 // 这个函数指定排序策略,按nID排序,如果nID相等的话,按strName排序。15 if (nID < _A.nID)16 return true;17 if (nID == _A.nID)18 return strName.compare(_A.strName) < 0;19 20 return false;21 }22 } StudentInfo, *PStudentInfo; // 学生信息23 24 void main()25 {26 // 用学生信息映射分数27 map mapStudent;28 StudentInfo studentInfo;29 studentInfo.nID = 1;30 studentInfo.strName = "student_one";31 mapStudent.insert(pair (studentInfo, 90));32 studentInfo.nID = 2;33 studentInfo.strName = "student_two";34 mapStudent.insert(pair (studentInfo, 80));35 }
2、解决方法2,仿函数。
1 // 解决方法2 2 3 #include4 #include 5 using namespace std; 6 7 typedef struct tagStudentInfo 8 { 9 int nID;10 string strName;11 } StudentInfo, *PStudentInfo; // 学生信息12 13 class sort14 {15 public:16 bool operator()(StudentInfo const & _A, StudentInfo const & _B) const17 {18 if (_A.nID < _B.nID)19 return true;20 if (_A.nID == _B.nID)21 return _A.strName.compare(_B.strName) < 0;22 23 return false;24 }25 };26 27 void main()28 {29 // 用学生信息映射分数30 map mapStudent;31 StudentInfo studentInfo;32 studentInfo.nID = 1;33 studentInfo.strName = "student_one";34 mapStudent.insert(pair (studentInfo, 90));35 studentInfo.nID = 2;36 studentInfo.strName = "student_two";37 mapStudent.insert(pair (studentInfo, 80));38 }
(6)待续...
【3】总结说明
(1)由于STL是一个统一的整体,map的很多用法都和STL中其它的东西结合在一起。
比如,在排序方面,这里默认用的是小于号,即less<>,如果要从大到小排序呢,这里涉及到的东西很多,在此无法一一加以说明。
(2)map容器内部有序,由红黑树保证,因此很多函数执行的时间复杂度都是log2N的,用map函数可以实现的功能,而STL Algorithm也可以完成该功能。
但是,建议用map自带函数,效率更高一些。
(3)map在空间上的特性。
由于map的每个数据对应红黑树上的一个节点,这个节点在不保存你的数据时,是占用16个字节:
一个父节点指针,左右两个孩子指针,还有一个枚举值(标示红黑的,相当于平衡二叉树中的平衡因子)。
Good Good Study, Day Day Up.
顺序 选择 循环 总结