关联容器的基本操作简单总结

本文深入探讨了C++ STL中的红黑树及其在set、multiset、map、multimap中的应用,详细阐述了这些数据结构的构建、插入、查找、删除、遍历等操作,并对比了它们的性能特点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

C++ STL中标准关联容器set, multiset, map, multimap内部采用的就是一种非常高效的平衡检索二叉树:红黑树,也成为RB树(Red-Black Tree)。RB树的统计性能要好于一般平衡二叉树,所以被STL选择作为了关联容器的内部结构。
这颗树具有对数据自动排序的功能,所以在map内部所有的数据都是有序的,后边我们会见识到有序的好处。
set&multiset
一,构建
set<int>s_val;
二,插入
s_val.insert(val);返回值:pair<set<int>::iterator,bool>;bool标志是否成功,前一个表示插入位置。若里面已经有此元素,则返回原元素的位置。
三,大小
s_val.size();元素的个数。
四,查找
count(val): 返回容器中值等于val的元素数目。
find(val): 返回容器中值等于val的第一个元素的iterator位置;如果没有匹配元素,则返回end()位置。
lower_bound(val): 返回容器中第一个值大于或等于val的元素的iterator位置。
upper_bound(val): 返回容器中第一个值大于val的元素的iterator位置。
equal_range(val): 返回容器中值等于val的所有元素的范围[beg, end)组成的pair<beg, end> 
五,判空&清空
s_val.clear()清空
s_val.empty()判空
六,删除
s_val.erase(val):删除容器中所有值为val的元素,返回删除元素的数目
s_val.erase(pos):删除位置为pos的元素。没有返回值。
s_val.erase(begin,end):删除范围内的所有元素。
七,遍历
set<int>::iterator iter;
iter=s_val.begin()第一个元素。
s_val.end()最后一个元素的下一个元素,
set<int>::reverse_iterator riterl;
riter=s_val.rbegin();最后一个元素。
s_val.rend(); 第一个元素的前一个元素。

map&&multimap
一,map构造方法:
map<int,string>map_ins;
二,map的插入:
1,insert()返回值:pair<set<int>::iterator,bool>;bool标志是否成功,前一个表示插入位置。若里面已经有此元素,则返回原元素的位置。
pair<int,string>p(v1,v2);
map_ins.insert(p);
while()
{
map_ins.insert(make_pair(v1,v2));
}
2,map_ins.inser(map<int,string>::value_type(v1,v2))
3,map_ins[1]="fdaslj";
三,map的大小
int nsize=map_ins.size();
四,数据的查找
1,用count函数来判定关键字是否出现,其缺点是无法定位数据位置,只有0和1
2,用find(第一个val)函数,如果有要找的数据则返回其元素的位置,否则返回end。
3,lower_bound(val),第一个返回容器中第一个key值大于或者小于val的元素的位置
   upper_bound(val)返回第一个key值大于val的元素的iterator的位置
4,equel_range(val):返回容器中等于val的所有元素的范围[beg, end)组成的pair<beg, end>;
五,数据的清空和判空;
clear()清空,empty()判空。
六,数据的删除
map_ins.erase(val):删除容器中所有key值为val的元素,成功返回删除元素的数目,否则0;
map_ins.erase(pos):删除位置为pos的元素。没有返回值。
map_ins.erase(begin,end):删除范围内的所有元素。
七,数据的遍历
map<int,string>::interator iter;
for(iter=map_ins.begin();iter!=map_ins.end();iter++)
  iter->second;
或者从后往前:
map<int,string>::reverse_interator riter;
rter.rbegin,容器中的最后一个元素。
rter.end,容器中的第一个元素的前一个元素。
C++中的无序关联容器(如 `std::unordered_map`、`std::unordered_multimap`、`std::unordered_set` 和 `std::unordered_multiset`)的底层数据结构基于**哈希表(hash table)**实现。这种数据结构通过哈希函数将键(key)映射到存储桶(buckets),每个存储桶可以包含一个或多个键-值对[^4]。 ### 哈希表的基本特性 1. **哈希函数**:无序关联容器使用哈希函数将键转换为整数,进而确定该键应被存储在哪个存储桶中。标准库提供了针对基本类型的默认哈希函数(例如 `std::hash<int>`、`std::hash<std::string>` 等),同时也允许用户自定义哈希函数。 2. **存储桶(Buckets)**:哈希表由多个存储桶组成,每个存储桶通常以链表的形式保存冲突的键-值对。当不同的键经过哈希函数后得到相同的存储桶索引时,它们会被存储在同一个链表中。 3. **负载因子(Load Factor)**:负载因子是衡量哈希表性能的重要指标,其定义为哈希表中元素总数与存储桶数量的比值。高负载因子可能导致更多的哈希冲突,从而影响性能。可以通过调整最大负载因子来控制哈希表的重新散列(rehashing)行为。 ### 时间复杂度分析 - **平均情况**:在理想情况下,哈希表的插入、删除和查找操作的时间复杂度为 $ O(1) $,即常数时间。 - **最坏情况**:当所有键都映射到同一个存储桶时,这些操作的时间复杂度退化为 $ O(n) $,其中 $ n $ 是元素总数。这种情况通常发生在哈希函数设计不佳或负载因子过高的情况下[^4]。 ### 无序关联容器的优势 - **快速访问**:由于底层使用哈希表,无序关联容器支持平均 $ O(1) $ 的查找、插入和删除操作。 - **灵活性**:支持用户自定义哈希函数和比较函数,使得容器能够适应各种类型的数据。 - **动态扩容**:当元素数量超过当前容量时,容器会自动进行重新散列,以保持较低的负载因子并优化性能。 ### 示例代码 以下是一个使用 `std::unordered_map` 的简单示例: ```cpp #include <iostream> #include <unordered_map> int main() { // 创建一个无序映射,键为字符串,值为整数 std::unordered_map<std::string, int> myMap; // 插入键值对 myMap["apple"] = 5; myMap["banana"] = 3; myMap["orange"] = 8; // 查找并输出键值对 std::cout << "apple: " << myMap.find("apple")->second << std::endl; std::cout << "banana: " << myMap.find("banana")->second << std::endl; std::cout << "orange: " << myMap.find("orange")->second << std::endl; return 0; } ``` ### 总结 无序关联容器的底层数据结构是哈希表,它通过高效的哈希函数和存储桶管理实现了快速的插入、删除和查找操作。然而,为了确保最佳性能,需要合理选择哈希函数并管理负载因子。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值