概述
map
和multimap
是C++ STL中的關聯容器,它們存儲的是鍵值對(key-value pairs),并且會根據鍵(key)自動排序。兩者的主要區別在于:
map
不允許重復的鍵multimap
允許重復的鍵
本文將詳細解析示例代碼中涉及的map
操作,包括賦值、排序、大小查詢和刪除等核心功能。
1. 頭文件與命名空間
#include <iostream>
#include <map>using namespace std;
#include <map>
:必須包含的頭文件,提供map
和multimap
的實現using namespace std
:使用標準命名空間,避免每次都要寫std::
2. 自定義排序規則(仿函數)
class CompareInt {
public:bool operator()(const int& left, const int& right) const {return left > right; // 降序排序}
};
- 仿函數(Functor):重載了
()
運算符的類,可以像函數一樣調用 - 這里實現了降序排序規則,當
left > right
時返回true
- 注意
operator()
應該聲明為const
,因為它不修改對象狀態
3. map的聲明與初始化
map<int, string> mapStu; // 默認less 升序排序
//map<int, string,greater<int>> mapStu; // greater 降序排序
//map<int, string,CompareInt> mapStu; // 使用自定義仿函數
- 默認排序:不指定第三個模板參數時,使用
less<Key>
,即升序排序 - 內置排序規則:可以使用
greater<Key>
實現降序排序 - 自定義排序:通過傳遞自定義的仿函數類型作為第三個模板參數
4. 插入元素
mapStu.insert(pair<int, string>(2, "小明"));
mapStu.insert(pair<int, string>(3, "廉頗"));
mapStu.insert(pair<int, string>(1, "妲己"));
mapStu.insert(pair<int, string>(4, "莊周"));
- insert():插入鍵值對
- 使用
pair
構造鍵值對,first
是鍵,second
是值 - 插入后元素會根據鍵自動排序
5. 拷貝構造與賦值
map<int, string> mapB(mapStu); // 拷貝構造
map<int, string> mapC = mapStu; // 賦值操作
- 拷貝構造:創建一個新map并復制所有元素
- 賦值操作:將已有map的所有元素復制到另一個map
- 兩種方式都會創建與原map完全相同的新容器
6. 元素訪問與修改
mapC[3] = "小喬"; // 通過鍵訪問并修改值
- operator[]:通過鍵訪問對應的值
- 如果鍵不存在,會自動插入該鍵,值為默認構造
7. 交換操作
mapC.swap(mapB); // 交換兩個map的內容
- swap():高效交換兩個map的內容
- 實際只交換內部指針,不復制元素,時間復雜度O(1)
8. 刪除操作
8.1 刪除區間元素
map<int, string>::iterator iBegin = mapB.begin();
++iBegin;
map<int, string>::iterator iEnd = mapB.end();
mapB.erase(iBegin, iEnd); // 刪除[iBegin, iEnd)區間
- erase(beg, end):刪除迭代器區間
[beg, end)
內的元素 - 區間是半閉半開的,包含
beg
但不包含end
- 返回void(新標準返回下一個元素的迭代器)
8.2 刪除單個元素
mapC.erase(mapC.begin()); // 刪除第一個元素
mapC.erase(4); // 刪除鍵為4的元素
- erase(pos):刪除迭代器
pos
指向的元素 - erase(key):刪除所有鍵等于
key
的元素(對于map
最多一個)
8.3 清空容器
mapC.clear(); // 清空所有元素
- clear():刪除容器中的所有元素,使size為0
8.4 刪除結果檢查
map<int, string, greater<int>>::size_type st = mapStu.erase(5);
cout << "st = " << st << endl; // 輸出刪除的元素個數
- **erase(key)**返回刪除的元素個數
- 對于
map
,返回值只能是0或1 - 對于
multimap
,返回值可以是任意非負整數
9. 大小查詢
if (!mapC.empty()) {cout << "mapC的大小: " << mapC.size() << endl;
}
- empty():檢查容器是否為空
- size():返回容器中元素的個數
- 通常先檢查
empty()
再調用size()
更安全
10. 迭代器遍歷
for (map<int, string, CompareInt>::iterator it = mapStu.begin(); it != mapStu.end(); it++) {cout << "key: " << (*it).first << " value: " << (*it).second << endl;
}
- begin()/end():獲取首元素和尾后迭代器
- 迭代器解引用得到
pair<const Key, Value>
- 可以用
it->first
和it->second
訪問鍵和值
完整代碼回顧
#include <iostream>
#include <map>using namespace std;// 仿函數用于比較int(降序排序)
class CompareInt {
public:bool operator()(const int& left, const int& right) const {return left > right; // 降序排序}
};int main(void) {map<int, string> mapStu; // 默認less 升序排序//map<int, string,greater<int>> mapStu; // greater 降序排序// 使用自定義的仿函數作為比較器//map<int, string,CompareInt> mapStu; mapStu.insert(pair<int, string>(2, "小明"));mapStu.insert(pair<int, string>(3, "廉頗"));mapStu.insert(pair<int, string>(1, "妲己"));mapStu.insert(pair<int, string>(4, "莊周"));// map對象的拷貝構造與賦值map<int, string> mapB(mapStu); // 拷貝構造for (map<int, string>::iterator it = mapB.begin(); it != mapB.end(); it++) {cout << "key: " << (*it).first << " value: " << (*it).second << endl;}cout << endl;map<int, string> mapC = mapStu; // 賦值for (map<int, string>::iterator it = mapC.begin(); it != mapC.end(); it++) {cout << "key: " << (*it).first << " value: " << (*it).second << endl;}cout << endl;mapC[3] = "小喬";mapC.swap(mapB);// map的刪除map<int, string>::iterator iBegin = mapB.begin();++iBegin;map<int, string>::iterator iEnd = mapB.end();mapB.erase(iBegin, iEnd); // 刪除區間mapC.erase(mapC.begin()); // 刪除第一個元素mapC.erase(4); // 刪除key為4的元素mapC.clear(); // 清空容器map<int, string, greater<int>>::size_type st = mapStu.erase(5);cout << "st = " << st << endl; // 輸出刪除個數// map的大小if (!mapC.empty()) {cout << "mapC的大小: " << mapC.size() << endl;}// 遍歷mapfor (map<int, string, CompareInt>::iterator it = mapStu.begin(); it != mapStu.end(); it++) {cout << "key: " << (*it).first << " value: " << (*it).second << endl;}system("pause");return 0;
}