条目二十三《考虑用排序的vector替代关联容器》

探讨在特定操作流程下,排序后的vector如何在性能上超越关联容器如map和set。在数据经历设置、查找、重组阶段而非频繁交错的插入和查找时,排序vector由于内存占用优势和减少页切换时间,展现出优于关联容器的性能。

条目二十三《考虑用排序的vector替代关联容器》

在看到这个条目的标题的时候,说实话,我一下子是比较懵逼的。这个结论怎么和数据结构的时间复杂度不一致了?

一般来说,像map,set等关联容器的底层因为是红黑树结构,那么即使红黑树的时间复杂度并非是绝对的对数时间,但也是稳定的接近对数时间。

然而类似vector这种序列容器的时间复杂度是线性的。

所以在涉及到对数据有查找操作的时候,在二者之间我基本是选择map或set的。

但是这条目毕竟是大神侯老爷子提出的,必定有其原因。好吧,看完几遍后,总算知道为何了。

适用情况:

这条目适合数据的操作步骤是:设置阶段,查找阶段,重组阶段。而不是元素插入和查找纠缠不清的情况。因为前者数据在设置阶段后可以直接调用sort()对vector排序,然后使用binary_search()等算法快速查找元素。

深究原因:

关联容器是由一个结点构成的树结构,每个节点由左右指针+父指针,元素值组成。而序列容器vector只由值组成,少了三个指针。在数据规模成千上万的情况下,关联容器占有的内存是比vector多了成千上万个指针大小的3倍。最要命的是占有的内存越多,分配的页内存就越多,所以系统花费更多的时间在页切换上,这个时间在数据规模非常大的时候是很乐观的。所以这种情况下排序的vector会比关联容器更快。

注意了,在stl中,还是对关键容器的内存分配做了局部优化处理的,就是通过底层优化,把同一个容器的内存分配尽量的分配在相邻的页中,这样会降低换页的性能消耗。

不过如果我们的环境是 数据经历设置,查找,重组阶段,而不是频繁且交错的插入和查找,最优的方案是排序的vector。反之,肯定是关联容器map或set,不然那将是一场性能灾难。

从这一条目,真的学习到了要把各个知识联系起来才行,不能把各个孤立起来,而是串在一起思考。。。

转载于:https://www.cnblogs.com/liangjf/p/10275037.html

### C++ STL Vector 和 Set 的区别及使用场景 #### Vector 特点与适用场景 Vector 是一种动态数组,支持随机访问,在内存中连续存储元素。对于频繁的顺序遍历操作非常高效。向量允许快速地在末端插入和删除元素,但在中间位置执行这些操作则需要移动大量元素,因此效率较低。 当面对一组固定数量或者增长缓慢的对象集合时,vector 是理想的选择。例如在一个班级中有100名学生的情况下,如果经常需要遍历整个列表或按索引查找特定的学生记录,则应优先考虑使用 vector[^3]。 ```cpp #include <iostream> #include <vector> int main() { std::vector<int> vec = {1, 2, 3}; // 访问元素 int firstElement = vec[0]; // 添加新元素到末尾 vec.push_back(4); } ``` #### Set 特点与适用场景 Set 实现了一个无序集合并自动去重的功能,内部通常基于红黑树或其他平衡二叉搜索树结构构建。这意味着所有的基本操作(如插入、删除以及成员测试)都具有 O(log n) 时间复杂度。由于其有序性质,set 非常适合用于处理唯一键值的情况,比如管理一系列不允许重复项的数据条目;另外也适用于那些仅需偶尔查询单个对象是否存在的情形。 假设同样是在一个拥有众多学生的环境中工作,但这次只关心个别同学的信息检索而不涉及全表扫描的话,那么采用 set 就更为合适了。特别是当人数增加至数千甚至上万级别时,通过 map 来定位指定个体将会带来更高的性能优势。 ```cpp #include <iostream> #include <set> int main() { std::set<int> s; // 插入元素 s.insert(1); s.insert(2); // 查找元素 bool containsTwo = s.find(2) != s.end(); } ``` #### 性能对比总结 - **时间复杂度** - 对于 `vector` 而言,获取任意位置处的元素只需 O(1),而在两端之外的位置插入/移除节点的时间成本较高,达到 O(n)[^1]。 - 相较之下,尽管 `set` 中读取、写入和删除任一项目均消耗 O(log n),然而它提供了更好的灵活性以应对更复杂的业务逻辑需求。 - **空间利用率** - `vector` 可能会预留额外的空间以便未来扩展,从而造成一定的浪费; - `set` 则不会预先分配多余容量,不过为了维持自平衡特性可能会占用更多实际使用的字节数。 综上所述,选择合适的容器取决于具体的应用背景及其对时间和空间的要求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值