在 C++ 標準模板庫(STL)中,map 是一個極其重要的關聯式容器,它以「鍵值對」的形式存儲數據,並根據鍵自動排序。無論是處理詞頻統計、配置管理,還是實現字典查找,map 都是首選工具。本文將系統梳理 map 的模板定義、核心特性、常用成員函數,並通過一個單詞計數的實戰案例,幫助你徹底掌握這個容器的精髓。
map 的完整模板聲明如下:
template < class Key, // map::key_type
class T, // map::mapped_type
class Compare = less<Key>, // map::key_compare
class Alloc = allocator<pair<const Key, T>> // map::allocator_type
> class map;
實例化時必須指定 Key 和 T(值類型),比較器 Compare 和配置器 Alloc 通常使用預設值,只有在自定義類型作為鍵且需要特殊排序規則時,才需提供自定義比較器。
less<Key>),遍歷時即為有序序列。O(log n)。pair<const Key, T>,即 value_type。// 型別別名
typedef pair<const Key, T> value_type;
typedef /*implementation-defined*/ iterator;
typedef /*implementation-defined*/ const_iterator;
typedef /*implementation-defined*/ reverse_iterator;
typedef /*implementation-defined*/ const_reverse_iterator;
其中 iterator 指向 value_type,解引用後可通過 it->first 訪問鍵、it->second 訪問值;const_iterator 僅允許只讀訪問;反向迭代器用於逆序遍歷。
| 分類 | 函數 | 說明 |
|---|---|---|
| 迭代器 | begin() / end() | 返回指向首元素 / 尾後位置的迭代器 |
rbegin() / rend() | 返回反向迭代器 | |
cbegin() / cend() | C++11 新增,返回常量迭代器 | |
crbegin() / crend() | C++11 新增,返回常量反向迭代器 | |
| 容量 | empty() | 判斷容器是否為空 |
size() | 返回元素個數 | |
| 元素訪問 | operator[](key) | 像數組一樣訪問值;若鍵不存在會自動插入一個值初始化的元素 |
at(key) | C++11 新增,邊界檢查版本,鍵不存在拋出 out_of_range | |
| 修改器 | insert(val) | 插入元素,若鍵已存在則不覆蓋,返回 pair<iterator,bool> |
erase(pos) | 按迭代器刪除單個元素 | |
erase(key) | 按鍵刪除,返回被刪除元素個數(0 或 1) | |
erase(first, last) | 刪除區間 [first, last) 內的所有元素 | |
clear() | 清空容器 | |
| 查找 | find(key) | 查找鍵,找到返回迭代器,否則返回 end() |
count(key) | 統計鍵出現次數,因鍵唯一,返回值只能是 0 或 1 |
經典場景:讀取標準輸入直到 EOF,統計每個單詞出現次數,最後按字典序輸出。
#include <iostream>
#include <map>
#include <string>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
map<string, int> word_count;
string word;
cout << "請輸入單詞(Ctrl+D 結束):\n";
while (cin >> word) {
// 方法 1:利用 operator[] 自動初始化為 0 再遞增
// word_count[word]++; // 簡潔但會多一次查找
// 方法 2:find + insert 避免多餘查找(教學示範)
auto it = word_count.find(word);
if (it == word_count.end()) {
word_count.insert({word, 1});
} else {
++(it->second);
}
}
cout << "不同單詞總數:" << word_count.size() << '\n';
for (const auto& kv : word_count) {
cout << "word: " << kv.first
<< " occur " << kv.second
<< " times\n";
}
return 0;
}
while (cin >> word) 會自動跳過空白字符,遇到 EOF 終止。word_count[word]++ 最常用,代碼簡潔且現代編譯器優化極好;find + insert 則展示了底層機制,適合面試講解。for (const auto& kv : word_count) 配合結構化綁定(C++17: for (auto& [k, v] : word_count))更加優雅。map<string, int, greater<>> mp;。operator[] 做只讀查找:它會修改容器(插入默認值),const map 上不可用,應改用 find 或 at。insert_or_assign、try_emplace,減少鍵值構造開銷。unordered_map(哈希表)平均 O(1) 更快,但失去有序遍歷能力。map 是 C++ 開發者工具箱中的「瑞士軍刀」:鍵值映射、自動排序、對數級查找,三大特性覆蓋了絕大多數關聯式存儲需求。熟練掌握其 API、理解紅黑樹特性帶來的迭代器失效規則、善用 C++11/17 新特性,能讓你在處理配置解析、詞頻統計、緩存實現等場景時游刃有餘。