Associative Container
按照关键字来保存和访问。map 和 set。
标准库提供8个关联容器:1. set或map; 2. 要求不重复的关键字,或者允许重复; 3. 按顺序保存元素或无序保存
1
| [unordered_][multi][map|set]
|
使用关联容器
multi_map
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| #include <iostream> #include <map> #include <string>
int main() { std::multimap<int, std::string> mm;
mm.insert({1, "apple"}); mm.insert({2, "banana"}); mm.insert({1, "apricot"}); mm.insert({3, "cherry"}); mm.insert({2, "blueberry"});
std::cout << "所有元素:" << std::endl; for (const auto& pair : mm) { std::cout << pair.first << ": " << pair.second << std::endl; }
int key = 2; std::cout << "\n键为 " << key << " 的所有值:" << std::endl; auto range = mm.equal_range(key); for (auto it = range.first; it != range.second; ++it) { std::cout << it->second << std::endl; }
std::cout << "\n键为 " << key << " 的元素数量:" << mm.count(key) << std::endl;
mm.erase(key); std::cout << "\n删除键 " << key << " 后剩余元素:" << std::endl; for (const auto& pair : mm) { std::cout << pair.first << ": " << pair.second << std::endl; }
return 0; }
|
pair<T1, T2> name = {v1, v2}
map / multimap的key的数据类型:
- 基本数据类型
- 自定义类型:必须定义比较规则 <, 自定义比较器(结构体)
关联容器操作
- key_type: 关键字类型
- mapped_type: 每个关键字关联的类型,只适用map
- value_type: for set, == key_type; for map, pair<const key_type, mapped_type>
迭代器:解引用得到value_type;set的迭代器为const
实际中,对一个关联容器使用算法,要么作为一个源序列,要么作为一个目的位置。
添加元素
insert, emplace(args): 插入一个存在的元素无影响, 返回pair,包含迭代器指向关键字的元素,以及一个指示是否插入成功的bool。对于multiset, multimap,总会插入成功,返回迭代器。
删除元素
erase(k): 删除关键字为k的元素
erase(p): 删除迭代器p指定的元素,p必须指向c中一个真实元素,不能等于c.end()。
erase(b, e): 删除迭代器对b和e所表示的范围中的元素,返回e
下标操作
map和unordered_map容器提供了下标运算符和一个对应的at函数
访问元素
find or count
对map使用find代替下标操作。如果下标运算符不在map中,会插入一个具有给定关键字的元素。
无序容器
新标准定义了四个无序关联容器,不使用比较运算符组织元素,使用一个哈希函数和关键字类型的==运算符。
默认情况下,无序容器使用关键字类型的==运算符来比较元素,还使用hash类型的对象来生成每个元素的哈希值。内置类型,string和智能指针具有hash模版。自定义类需要定义hash函数和==运算符的函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
| #include <iostream> #include <string> #include <unordered_set> #include <functional>
class Student { private: std::string name; int id;
public: Student(std::string n, int i) : name(n), id(i) {}
std::string get_name() const { return name; } int get_id() const { return id; }
bool operator==(const Student& other) const { return this->id == other.id; } };
namespace std { template<> struct hash<Student> { size_t operator()(const Student& s) const { size_t id_hash = hash<int>()(s.get_id()); size_t name_hash = hash<string>()(s.get_name());
return id_hash ^ (name_hash << 1); } }; }
int main() { std::unordered_set<Student> students;
students.insert(Student("Alice", 1001)); students.insert(Student("Bob", 1002)); students.insert(Student("Charlie", 1003)); students.insert(Student("Alice", 1001));
std::cout << "所有学生:" << std::endl; for (const auto& s : students) { std::cout << "学号:" << s.get_id() << ",姓名:" << s.get_name() << std::endl; }
Student target("David", 1002); auto it = students.find(target); if (it != students.end()) { std::cout << "\n找到学生:学号=" << it->get_id() << ",姓名=" << it->get_name() << std::endl; } else { std::cout << "\n未找到学生" << std::endl; }
return 0; }
|