文章目錄
- 1. 定義與初始化
- 2. 插入元素
- 3. 查找元素
- 4. 刪除元素
- 5. 遍歷
- 6. 訪問成員函數
- 7. 修改元素
- 8. 注意事項
- 9. 使用 `equal_range` 查找鍵值范圍
- 10. 使用 `emplace` 添加元素
- 11. 使用 `cbegin` 和 `cend` 獲取常量迭代器
- 12. 排序規則自定義
- 13. 使用 `multimap` 存儲重復鍵
- 14. 判斷 map 是否包含某個鍵
- 15. 訪問 map 的第一個和最后一個元素
- 16. 使用 `emplace_hint` 插入元素
- 17. 使用 `extract` 移除并返回元素
- 18. 使用 `merge` 合并兩個 map
- 19. 使用 `extract` 和 `insert` 實現元素移動
- 20. 使用 `swap` 函數交換兩個 map 的內容
- 21. 使用 `lower_bound` 和 `upper_bound` 實現范圍查找
- 22. 使用 `emplace_hint` 并結合 `find` 獲取更好的插入性能
- 23. 使用 `key_comp` 和 `value_comp` 比較器
- 24. 使用 `equal_range` 進行精確查找
- 25. 使用 `max_size` 查詢最大容量
- 26. 使用 `reserve` 預留空間
- 27. 使用 `extract` 與 `emplace` 實現原子化的更新操作
- 28. 使用 `extract` 移除元素并轉換為普通對象
- 29. 使用 `extract` 清空 map
- 30. 使用 `std::transform` 迭代 map 并應用函數
- 31. 使用 `std::copy` 將 map 轉換為 vector
- 32. 使用 `std::all_of`, `std::any_of`, `std::none_of` 對 map 進行條件檢查
- 33. 使用 `std::accumulate` 計算 map 中所有值的總和
- 34. 使用 `std::for_each` 對 map 進行遍歷并打印
- 35. 使用 `std::map::extract` 結合 `std::set` 移除特定鍵集合中的元素
- 36. 使用 `std::map::emplace_hint` 更新已存在的鍵值對
- 37. 使用 `std::unordered_map` 改善查找性能(散列映射)
- 38. 使用 `std::map::key_type` 和 `mapped_type` 獲取鍵和值的類型
- 39. 使用 `std::advance` 移動迭代器
- 40. 使用 `std::prev` 和 `std::next` 訪問相鄰元素
C++ map用法詳細總結
C++ 中的 std::map
是標準庫中的一種關聯容器,它提供了一種鍵值對的存儲方式,其中鍵是唯一的,并且按照升序排序。以下是對 std::map
的詳細用法總結:
1. 定義與初始化
#include <map>
using namespace std;// 聲明一個 map,鍵為 string 類型,值為 int 類型
map<string, int> myMap;// 直接初始化
map<string, int> myMap2 = {{"Alice", 85},{"Bob", 90},{"Charlie", 95}
};
2. 插入元素
// 插入單個鍵值對
myMap["David"] = 88;// 使用 insert 方法插入
pair<map<string, int>::iterator, bool> result = myMap.insert({"Eve", 92});
3. 查找元素
// 查找鍵
auto it = myMap.find("Alice");
if (it != myMap.end()) {cout << "Alice's grade: " << it->second << endl;
} else {cout << "Alice not found." << endl;
}// 使用 at() 獲取值,若鍵不存在則拋出異常
try {cout << "Charlie's grade: " << myMap.at("Charlie") << endl;
} catch (const out_of_range&) {cout << "Charlie not found." << endl;
}
4. 刪除元素
// 刪除指定鍵的元素
myMap.erase("Alice");// 刪除迭代器指向的元素
auto it2 = myMap.find("Bob");
if (it2 != myMap.end()) {myMap.erase(it2);
}
5. 遍歷
// 使用迭代器遍歷
for (auto it = myMap.begin(); it != myMap.end(); ++it) {cout << it->first << ": " << it->second << endl;
}// 使用范圍for循環遍歷
for (const auto& entry : myMap) {cout << entry.first << ": " << entry.second << endl;
}
6. 訪問成員函數
size()
:返回 map 中元素的數量。empty()
:如果 map 為空則返回true
,否則返回false
。clear()
:清空 map 內的所有元素。count(key)
:返回 key 出現的次數(對于 map 總是 0 或 1,因為鍵是唯一的)。lower_bound(key)
和upper_bound(key)
:返回指向首個大于等于(小于)key的元素的迭代器。
7. 修改元素
// 更新已有鍵的值
myMap["David"] = 90;
8. 注意事項
- map 中的鍵值對是根據鍵的升序排列的。
- map 的鍵是不可變的,一旦插入就不能更改鍵的值。
- map 的迭代器在刪除元素時可能會失效,除非你使用的是
erase()
返回的新迭代器。
以上總結了C++中 std::map
關鍵用法,實際使用時應根據具體需求選擇合適的方法操作。
9. 使用 equal_range
查找鍵值范圍
equal_range
函數返回一個迭代器對,該對包含 map 中與給定鍵相等的所有元素的范圍(對于 map,始終只有一個元素)。這對于在已排序的鍵值對中查找鍵值范圍特別有用。
auto range = myMap.equal_range("Bob");for (auto it = range.first; it != range.second; ++it) {cout << it->first << ": " << it->second << endl;
}
10. 使用 emplace
添加元素
emplace
函數可以在 map 中直接構造(而不是拷貝或移動)元素,從而節省時間和空間。它接受與 map 鍵值對類型相同的參數。
myMap.emplace("Frank", 93); // 直接在map中構造新的鍵值對
11. 使用 cbegin
和 cend
獲取常量迭代器
當你需要在不影響 map 的情況下遍歷其元素時,可以使用 cbegin()
和 cend()
獲取常量迭代器。
for (const auto& entry : myMap) {// 使用常量引用,不會修改 map 中的元素
}// 或者使用常量迭代器
for (auto it = myMap.cbegin(); it != myMap.cend(); ++it) {// ...
}
12. 排序規則自定義
默認情況下,std::map
的鍵按照 <
運算符進行排序。如果要使用其他比較函數,可以提供一個自定義的比較器。
struct CustomComparator {bool operator()(const std::string& a, const std::string& b) const {return a.length() < b.length(); // 按字符串長度排序}
};std::map<std::string, int, CustomComparator> myCustomMap;
13. 使用 multimap
存儲重復鍵
std::multimap
類似于 std::map
,但允許有重復的鍵,每個鍵可以關聯多個值。
總之,C++ std::map
提供了豐富的功能,支持高效的鍵值對存儲和檢索,尤其適合那些需要根據鍵排序并保持唯一性的場景。通過熟練掌握上述用法,你可以更好地利用這一強大工具。
14. 判斷 map 是否包含某個鍵
除了使用 find
函數檢查鍵是否存在之外,也可以直接使用 count
函數。count
函數返回鍵在 map 中出現的次數,對于 map 來說,如果鍵存在則返回1,否則返回0。
if (myMap.count("Alice") > 0) {cout << "Alice is in the map." << endl;
} else {cout << "Alice is not in the map." << endl;
}
15. 訪問 map 的第一個和最后一個元素
begin()
返回指向 map 中第一個元素(按鍵值排序)的迭代器。end()
返回指向 map 結束點的迭代器,不指向任何元素。rbegin()
和rend()
分別返回逆向迭代器,指向 map 中最后一個元素(按鍵值排序)和逆向迭代器的結束點。
// 輸出 map 中的第一個元素
if (!myMap.empty()) {std::cout << "First element: " << myMap.begin()->first << ": " << myMap.begin()->second << std::endl;
}// 輸出 map 中的最后一個元素
if (!myMap.empty()) {std::cout << "Last element: " << myMap.rbegin()->first << ": " << myMap.rbegin()->second << std::endl;
}
16. 使用 emplace_hint
插入元素
emplace_hint
函數類似于 emplace
,但在已經知道插入點的情況下,可以提供一個迭代器提示,有可能提高插入效率。
auto hint = myMap.lower_bound("David"); // 獲取可能的插入點
myMap.emplace_hint(hint, "Eve", 91); // 在 "David" 之后或相應位置插入新的鍵值對
17. 使用 extract
移除并返回元素
C++17 引入了 extract
函數,可以從容器中移除元素并返回一個包含該元素的 std::pair
,其中 .first
是指向元素的迭代器,.second
是一個包含了原容器中元素的 std::optional
。
if (auto result = myMap.extract("Alice"); result.second) {std::cout << "Removed Alice with grade: " << result.first->second << std::endl;// 可以將移除的元素插入到另一個 map 中anotherMap.insert(std::move(result.first));
}
通過熟悉這些高級用法和功能,開發者可以更加靈活高效地使用 C++ 的 std::map
容器。
18. 使用 merge
合并兩個 map
C++17 中引入了 merge
函數,可以將一個 map 的內容合并到另一個 map 中,合并過程中如果遇到相同鍵值,后者會替換前者。
std::map<std::string, int> map1 = {{"Alice", 85}, {"Bob", 90}};
std::map<std::string, int> map2 = {{"Bob", 92}, {"Charlie", 95}};map1.merge(map2); // 合并后,map1 中 Bob 的成績變為 92// map1: {"Alice": 85, "Bob": 92, "Charlie": 95}
// map2: {}
19. 使用 extract
和 insert
實現元素移動
extract
函數可以配合 insert
函數實現元素在 map 間的移動,而不僅僅是復制。
std::map<std::string, int> map1, map2;// ... 填充 map1 和 map2 ...// 將 map1 中的 "Alice" 移動到 map2
if (auto it = map1.extract("Alice"); it.second) {map2.insert(std::move(it.mapped()));
}// 此時 map1 不再包含 "Alice"
20. 使用 swap
函數交換兩個 map 的內容
swap
函數可以交換兩個 map 的所有內容,包括內部的鍵值對及其順序。
std::map<std::string, int> map1 = {{"Alice", 85}, {"Bob", 90}};
std::map<std::string, int> map2 = {{"Charlie", 95}, {"David", 98}};std::swap(map1, map2);// 交換后,map1 和 map2 的內容互換
通過學習和實踐以上 std::map
的各種用法,開發者能夠更好地應對不同場景下的鍵值對存儲和查詢需求,編寫出高效且易于維護的代碼。
當然,以下是更多的 std::map
使用示例:
21. 使用 lower_bound
和 upper_bound
實現范圍查找
這兩個函數可以用來找到 map 中第一個大于等于(小于)指定鍵的元素,適用于查找某一鍵值范圍內的所有元素。
std::map<std::string, int> grades = {{"Alice", 85}, {"Bob", 90}, {"Charlie", 95}, {"David", 98}};auto lower = grades.lower_bound("Bob");
auto upper = grades.upper_bound("David");for (auto it = lower; it != upper; ++it) {std::cout << it->first << ": " << it->second << std::endl;
}
// 輸出:Bob: 90 Charlie: 95
22. 使用 emplace_hint
并結合 find
獲取更好的插入性能
當已知要插入的位置附近時,可以先用 find
查找,然后將返回的迭代器作為 emplace_hint
的參數。
std::map<std::string, int> grades;
auto it = grades.find("Bob");
grades.emplace_hint(it, "Alice", 85); // 如果 "Bob" 已經在 map 中,那么 "Alice" 將插入在其之前
23. 使用 key_comp
和 value_comp
比較器
key_comp
返回一個可以用來比較鍵的仿函數,value_comp
返回一個可以用來比較元素(鍵值對)的仿函數。
std::map<std::string, int> grades;// 檢查兩個鍵是否按 map 的排序規則相等
if (grades.key_comp()("Alice", "Bob") == 0) {// ...
}// 檢查兩個鍵值對是否按 map 的排序規則相等
if (grades.value_comp()(std::make_pair("Alice", 85), std::make_pair("Bob", 90)) == 0) {// ...
}
24. 使用 equal_range
進行精確查找
equal_range
返回一個迭代器對,表示 map 中所有鍵等于給定鍵的元素范圍,對于 map,這始終只包含一個元素。
auto range = grades.equal_range("Alice");
assert(range.first == range.second); // 如果 "Alice" 不存在于 map 中,兩者相等
25. 使用 max_size
查詢最大容量
max_size
函數返回 map 可能容納的最大元素數量,但實際可用空間可能受系統限制影響。
std::size_t maxSize = grades.max_size();
std::cout << "Max possible size of grades map: " << maxSize << std::endl;
26. 使用 reserve
預留空間
雖然 map 不能像 vector 那樣直接預留空間,但它會根據需要動態調整內部數據結構,以適應增加的元素。
27. 使用 extract
與 emplace
實現原子化的更新操作
可以提取元素、修改其值,然后重新插入,確保在多線程環境下的原子性。
if (auto entry = grades.extract("Bob"); entry.second) {entry.mapped() = 92; // 修改值grades.emplace_hint(entry.position(), std::move(entry)); // 重新插入
}
28. 使用 extract
移除元素并轉換為普通對象
extract
函數可以將 map 中的元素提取出來,并轉換為一個普通的鍵值對(std::pair<const Key, T>
)。
if (auto entry = grades.extract("Bob"); entry.second) {std::pair<const std::string, int> extractedPair = *entry;// 使用 extractedPair 進行進一步操作
}
29. 使用 extract
清空 map
可以通過連續調用 extract
并忽略返回值來清空 map。
while (!grades.empty()) {grades.extract(grades.begin());
}
30. 使用 std::transform
迭代 map 并應用函數
結合迭代器和 std::transform
函數,可以對 map 中的所有值執行某種計算。
std::map<std::string, int> gradesCopy;
std::transform(grades.begin(), grades.end(),std::inserter(gradesCopy, gradesCopy.end()),[](const auto& pair) {return std::make_pair(pair.first, pair.second * 2); // 示例:將成績加倍});
以上示例展現了 std::map
更多的特性和用法,幫助開發者深入了解并有效地使用這一容器。
31. 使用 std::copy
將 map 轉換為 vector
可以將 map 的鍵或值復制到 vector 中。
std::vector<std::string> keys;
std::copy(grades.begin(), grades.end(),std::back_inserter(keys),[](const auto& pair) { return pair.first; });std::vector<int> values;
std::transform(grades.begin(), grades.end(),std::back_inserter(values),[](const auto& pair) { return pair.second; });
32. 使用 std::all_of
, std::any_of
, std::none_of
對 map 進行條件檢查
bool allAbove90 = std::all_of(grades.begin(), grades.end(),[](const auto& pair) { return pair.second > 90; });bool anyBelow80 = std::any_of(grades.begin(), grades.end(),[](const auto& pair) { return pair.second < 80; });bool noneEqual95 = std::none_of(grades.begin(), grades.end(),[](const auto& pair) { return pair.second == 95; });
33. 使用 std::accumulate
計算 map 中所有值的總和
int totalScore = std::accumulate(grades.begin(), grades.end(), 0,[](int sum, const auto& pair) { return sum + pair.second; });
34. 使用 std::for_each
對 map 進行遍歷并打印
std::for_each(grades.begin(), grades.end(),[](const auto& pair) { std::cout << pair.first << ": " << pair.second << std::endl; });
35. 使用 std::map::extract
結合 std::set
移除特定鍵集合中的元素
std::set<std::string> studentsToRemove = {"Alice", "Bob"};
for (const auto& student : studentsToRemove) {if (auto it = grades.extract(student); it.second) {// 已成功移除學生}
}
36. 使用 std::map::emplace_hint
更新已存在的鍵值對
auto it = grades.find("Charlie");
if (it != grades.end()) {grades.emplace_hint(it, "Charlie", it->second + 1); // 假設將成績增加1分
}
37. 使用 std::unordered_map
改善查找性能(散列映射)
在某些場景下,如果你不需要鍵有序且查找速度更為關鍵,可以考慮使用 std::unordered_map
。
std::unordered_map<std::string, int> unorderedGrades;
// ... 插入和訪問方式類似 ...
38. 使用 std::map::key_type
和 mapped_type
獲取鍵和值的類型
using StudentName = std::map<std::string, int>::key_type;
using Grade = std::map<std::string, int>::mapped_type;
39. 使用 std::advance
移動迭代器
auto it = grades.begin();
std::advance(it, 2); // 移動到第三個元素的位置
40. 使用 std::prev
和 std::next
訪問相鄰元素
auto it = std::next(grades.begin()); // 第二個元素
auto previous = std::prev(it); // 第一個元素
auto next = std::next(it); // 第三個元素
請注意,在實際項目中,應結合具體情況合理使用這些技術,以達到代碼簡潔、高效的目的。
python推薦學習匯總連接:
50個開發必備的Python經典腳本(1-10)
50個開發必備的Python經典腳本(11-20)
50個開發必備的Python經典腳本(21-30)
50個開發必備的Python經典腳本(31-40)
50個開發必備的Python經典腳本(41-50)
————————————————
?最后我們放松一下眼睛