关联容器

STL关联容器解析
本文介绍了STL中的关联容器,包括map、set、multimap和multiset的特点与使用方法。详细探讨了这些容器如何存储键值对,以及如何通过键进行高效查找。此外,还对比了不同容器间的差异。

关联容器

1.map类型

map定义的类型:
map<K, V>::key_type   //在map容器中用作索引的键的类型
map<K, V>::mapped_type   //在map容器中用作值的类型
map<K, V>::value_type   //一个pair类型,它的first元素具有const map<K, V>::key_type类型,而second元素具则为map<K, V>::mapped_type类型

1.1map迭代器进行解引用产生pair类型的对象

对迭代器进行解引用获得一个pair类型对象,它的first成员存放键,为const,因此键一旦生成便不能更改
map<string, int> word_count;
 it->first = "new key";//出错,键不能更改
 map<string, int>::iterator it = word_count.begin();

1.2使用下标访问访问map对象

使用下标访问map与使用下标访问数组或vector截然不同:用下标访问不存在的元素将导致在map容器中添加一个新的元素,它的键即为该下标值

1.3查找并读取map中的元素

1.3.1使用count检查map对象中某键是否存在
count成员返回值只能为0或1,因为map容器只允许一个键对应一个实例。
1.3.2读取元素而又不插入元素
find操作返回只想元素的迭代器,如果元素不存在,返回end迭代器。
因此,判断元素存在用count,如果希望当元素存在时就是用它,则使用find操作,然后使用它返回的迭代器进行操作。

2.set类型

set类型中只能保存键不同的元素,同样建不能修改,为const类型。

3.multimap和multiset类型

multmap和multset类型允许一个键对应多个实例,但是multmap不支持下标运算,因为一个键可能对应多个值。

3.1元素的添加和删除

一个作者可以写多本书:
multimap<string, string> authors;
authors.insert(make_pair(string("Barth, John"), string("Sot-weed Factor")));
authors.insert(make_pair(string("Barth, John"), string("Lost in the Funhouse")));//正确,一个作者写了两本书
带有一个键参数的erase版本将删除拥有该键的所有元素,并返回删除元素的个数。而带有一个或者一对迭代器参数的版本只删除指定的元素。
3.2在multimap和multiset中查找元素
用例:某键对应的元素可能出现多次(假设有作者与书名的映射,找到并输出某个作者的所有书的书名)
3.2.1使用find和count操作
multimap<string, string> authors;
authors.insert(make_pair(string("name"), string("123")));
authors.insert(make_pair(string("name"), string("456")));
authors.insert(make_pair(string("name"), string("789")));
string search_item("name");
typedef multimap<string ,string>::size_type sz_type;//定义类型
sz_type entries = authors.count(search_item);
multimap<string, string>::iterator iter = authors.find(search_item);//根据cnt来递增迭代器
for(sz_type cnt=0; cnt!=entries; ++cnt, ++iter)
	cout<<iter->second<<endl;//输出值
3.2.2面向迭代器的解决方案
使用关联容器操作:lower_bound和upper_bound:在同一个键上调用lower_bound和upper_bound将产生一个迭代器范围,指示该键所关联的所有元素(注意可能返回超出末端的迭代器)
multimap<string, string> authors;
authors.insert(make_pair(string("name"), string("123")));
authors.insert(make_pair(string("name"), string("456")));
authors.insert(make_pair(string("name"), string("789")));
typedef multimap<string, string>::iterator authors_it;
string search_item("name");//要查找的键
authors_it beg = authors.lower_bound(search_item);//获取低端迭代器
authors_it end = authors.upper_bound(search_item);//获取高端迭代器
while(beg != end)//遍历
{
	cout<<beg->second<<endl;//输出值
	++beg;//递增迭代器
}

3.2.3equsl_range函数来解决
调用equal_range函数来取代调用upper_bound和lower_bound函数。equal_range返回存储一对迭代器的pair对象。如果该值存在,则pair对象中的第一个迭代器指向该键关联的第一个实例,第二个迭代器指向该键关联的最后一个实例的下一个位置
multimap<string, string> authors;
authors.insert(make_pair(string("name"), string("123")));
authors.insert(make_pair(string("name"), string("456")));
authors.insert(make_pair(string("name"), string("789")));
typedef multimap<string, string>::iterator authors_it;
string search_item("name");//要查找的键
pair<authors_it, authors_it> pos = authors.equal_range(search_item);//获取迭代器范围
while(pos.first != pos.second)//循环
{
	cout<<pos.first->second<<endl;//输出第一个迭代器里面的值
	++pos.first;//迭代器自增



就到这里吧,看了STL源码剖析在进一步分析STL的强大。




C++中的关联容器是一类用于存储和管理键值对(Key-Value Pairs)的数据结构,它们提供了高效的查找、插入和删除操作。关联容器基于二叉搜索树或哈希表实现,因此在查找时具有对数时间复杂度(如`map`、`set`)或常数时间复杂度(如`unordered_map`、`unordered_set`)。 ### 关联容器的类型 C++标准库提供了以下主要的关联容器: 1. **`set`** - 存储唯一的键(key),键值本身即为元素。 - 内部结构基于红黑树,键默认按升序排列。 - 键是常量(`const`),不可修改,只能删除后重新插入。 - 示例: ```cpp std::set<int> s; s.insert(10); s.insert(20); ``` 2. **`multiset`** - 与`set`类似,但允许重复键值。 - 示例: ```cpp std::multiset<int> ms; ms.insert(10); ms.insert(10); // 允许重复插入 ``` 3. **`map`** - 存储键值对(`pair<const Key, T>`),键唯一。 - 值通过键进行快速查找。 - 键是常量,但值可修改。 - 示例: ```cpp std::map<std::string, int> m; m["apple"] = 5; m.insert(std::make_pair("banana", 3)); ``` 4. **`multimap`** - 与`map`类似,但允许重复键。 - 示例: ```cpp std::multimap<int, std::string> mm; mm.insert({1, "one"}); mm.insert({1, "uno"}); // 允许重复键 ``` 5. **`unordered_set`** 和 **`unordered_multiset`** - 使用哈希表实现,不保证元素顺序。 - 插入和查找操作平均为常数时间复杂度。 - `unordered_set`不允许重复键,`unordered_multiset`允许。 6. **`unordered_map`** 和 **`unordered_multimap`** - 类似于`map`和`multimap`,但基于哈希表实现。 - 示例: ```cpp std::unordered_map<std::string, int> um; um["apple"] = 5; ``` ### 关联容器的基本操作 - **插入元素** 使用`insert()`方法插入元素,对于`map`也可以使用`operator[]`直接赋值[^3]。 ```cpp std::map<int, std::string> m; m.insert(std::make_pair(1, "one")); m[2] = "two"; // 更简洁的方式 ``` - **查找元素** 使用`find()`方法查找指定键,返回迭代器。 ```cpp auto it = m.find(2); if (it != m.end()) { std::cout << it->second << std::endl; // 输出 "two" } ``` - **删除元素** 使用`erase()`方法删除指定键或迭代器位置的元素。 ```cpp m.erase(2); // 删除键为2的元素 ``` - **遍历元素** 使用迭代器遍历容器,注意关联容器迭代器是按关键字升序排列的[^2]。 ```cpp for (const auto& kv : m) { std::cout << kv.first << ": " << kv.second << std::endl; } ``` ### 关联容器的特性 - **键的不可变性** 在`map`、`set`等容器中,键是`const`类型,不能被修改,只能通过删除后重新插入来更新键值。 - **排序行为** `map`、`set`等容器默认使用`<`运算符进行排序,可以通过自定义比较器来改变排序规则。 - **效率** - `set`、`map`等基于红黑树实现,查找、插入、删除操作的时间复杂度为`O(log n)`。 - `unordered_set`、`unordered_map`基于哈希表实现,平均时间复杂度为`O(1)`。 ### 示例代码:使用`map`存储和查找数据 ```cpp #include <iostream> #include <map> #include <string> int main() { std::map<std::string, int> word_count; // 插入数据 word_count["apple"] = 3; word_count["banana"] = 2; // 查找数据 auto it = word_count.find("apple"); if (it != word_count.end()) { std::cout << "apple count: " << it->second << std::endl; } // 遍历数据 for (const auto& pair : word_count) { std::cout << pair.first << ": " << pair.second << std::endl; } return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值