
C++ 的 unordered_map 是标准模板库(STL)中的一个关联容器,它存储键值对,并通过哈希函数实现快速查找。以下是关于 unordered_map 的详细概览:
#include <unordered_map>
// 默认构造函数
unordered_map<int,string> map1;
// 初始化列表构造
unordered_map<int,string> map2 = {{1, "apple"}, {2, "banana"}};
// 拷贝构造
unordered_map<int,string> map3(map2);
// 插入元素
map1.insert({3, "cherry"}); // 方式 1:插入键值对
map1[4] = "date"; // 方式 2:通过[]赋值(不存在则创建)
// 访问元素
cout << map1[3]; // 通过键访问(键不存在时会插入默认值)
cout << map1.at(3); // 通过键访问(键不存在时抛出 out_of_range 异常)
// 修改元素
map1[3] = "grape"; // 修改已存在的键对应的值
// 删除元素
map1.erase(3); // 删除键为 3 的元素
map1.erase(map1.find(4)); // 通过迭代器删除
map1.clear(); // 清空所有元素
// 查找键是否存在
if(map1.find(2) != map1.end()) { // find 返回迭代器,不存在时返回 end()
cout << "Key 2 exists";
}
// 统计键的数量(只能是 0 或 1)
if(map1.count(2) > 0) { // count 返回键的出现次数
cout << "Key 2 exists";
}
bool empty = map1.empty(); // 判断是否为空
size_t size = map1.size(); // 返回元素个数
size_t max_size = map1.max_size(); // 返回最大容量
// 遍历所有元素(使用范围 for 循环更简洁)
for(const auto& pair: map1) {
cout << pair.first << ": " << pair.second << endl;
}
// 使用迭代器遍历
for(auto it = map1.begin();it != map1.end(); ++it) {
cout << it->first << ": " << it->second << endl;
}
size_t bucket_count = map1.bucket_count(); // 返回桶的数量
size_t bucket = map1.bucket(2); // 返回键 2 所在的桶索引
float load_factor = map1.load_factor(); // 返回负载因子(元素数/桶数)
float max_load_factor = map1.max_load_factor(); // 返回最大负载因子
map1.rehash(10); // 重新调整桶的数量(至少为 10)
哈希函数与键比较:
struct MyKey {
int x,y;
bool operator==(const MyKey& other)const {
return x == other.x && y == other.y;
}
};
// 自定义哈希函数
struct MyHash {
size_t operator()(const MyKey& k)const {
return std::hash<int>()(k.x) ^ (std::hash<int>()(k.y) << 1);
}
};
unordered_map<MyKey,string,MyHash> customMap;
键的不可修改性:
性能考虑:
rehash() 或 reserve() 提前调整桶数量。map 的对比| 特性 | unordered_map |
map |
|---|---|---|
| 底层实现 | 哈希表 | 红黑树(平衡二叉搜索树) |
| 元素顺序 | 无序 | 按键升序排列 |
| 插入 / 查找效率 | 平均 O(1),最坏 O(n) | O(log n) |
| 内存占用 | 较高(需维护哈希表和桶) | 较低(仅需维护树结构) |
| 适用场景 | 快速查找、无需顺序 | 需要有序遍历、对内存敏感 |
C++ 的 std::string 是标准模板库(STL)中用于处理字符串的类,它封装了动态字符数组,并提供了丰富的操作函数。以下是关于 std::string 的详细概览:
'\0' 结尾)。char(或 wchar_t、char16_t 等宽字符类型)。cpp
#include <string>
// 默认构造
string s1; // 空字符串
// 从 C 风格字符串构造
string s2("hello"); // s2 = "hello"
string s3 = "world"; // s3 = "world"
// 复制构造
string s4(s2); // s4 = "hello"
// 部分复制
string s5("abcdef",3); // s5 = "abc"(前 3 个字符)
// 重复字符
string s6(5, 'A'); // s6 = "AAAAA"
cpp
// 拼接
string s = s2 + " " + s3; // s = "hello world"
s.append("!"); // s = "hello world!"
s += "??"; // s = "hello world!??"
// 插入
s.insert(6, "beautiful"); // s = "hello beautiful world!??"
// 删除
s.erase(11,5); // 删除从位置 11 开始的 5 个字符,s = "hello beautiful!??"
// 替换
s.replace(6,9, "cruel"); // 从位置 6 开始的 9 个字符替换为"cruel",s = "hello cruel!??"
// 清空
s.clear(); // s = ""
cpp
string str = "hello world";
// 查找子串
size_t pos = str.find("world"); // pos = 6(第一次出现的位置)
if(pos!= string::npos) { // string::npos 表示未找到
cout << "Found at position" << pos << endl;
}
// 反向查找
pos = str.rfind("l"); // pos = 9(最后一次出现的位置)
// 比较
bool equal = (str == "hello world"); // true
int cmp = str.compare("hello"); // 大于 0(按字典序比较)
cpp
string substr = str.substr(6,5); // 从位置 6 开始的 5 个字符,substr = "world"
// 转为 C 风格字符串
const char* c_str = str.c_str(); // 返回以'\0'结尾的字符指针
cpp
#include <algorithm>
// 转为大写
transform(str.begin(),str.end(),str.begin(), ::toupper); // str = "HELLO WORLD"
// 转为小写
transform(str.begin(),str.end(),str.begin(), ::tolower); // str = "hello world"
cpp
bool empty = str.empty(); // 判断是否为空
size_t len = str.length(); // 返回字符串长度(同 size())
size_t size = str.size(); // 返回字符串长度
size_t capacity = str.capacity(); // 返回当前分配的容量
str.reserve(100); // 预分配至少 100 个字符的容量
str.resize(20, 'x'); // 调整长度为 20,不足部分用'x'填充
cpp
// 正向遍历
for(auto it = str.begin();it != str.end(); ++it) {
cout << *it;
}
// 反向遍历
for(auto rit = str.rbegin();rit != str.rend(); ++rit) {
cout << *rit;
}
// 范围 for 循环(C++11+)
for(char c: str) {
cout << c;
}
cpp
// 数值转字符串(C++11+)
string numStr = to_string(12345); // numStr = "12345"
string floatStr = to_string(3.14); // floatStr = "3.140000"
// 字符串转数值(C++11+)
int num = stoi("123"); // num = 123
double d = stod("3.14"); // d = 3.14
long long ll = stoll("9223372036854775807"); // 大整数
// 错误处理(转换失败时抛出异常)
try {
int invalid = stoi("abc");
} catch(const invalid_argument& e) {
cout << "Invalid number" << endl;
}
性能考虑:
reserve() 预分配内存。+= 和 append() 比 insert() 效率更高。字符编码:
std::string 默认处理单字节字符(如 ASCII),处理多字节字符(如 UTF-8)时需注意编码规则。与 C 风格字符串的转换:
c_str() 获取 C 风格字符串指针。 data() 在 C++11 及以后与 c_str() 功能相同(返回以 '\0' 结尾的指针)。