两者有什么区别?我的意思是方法都是一样的。因此,对于用户来说,他们的工作方式相同。
这是正确的吗?
答案 0 :(得分:104)
让我列出差异:
<强>复杂性强>
Insert/erase at the beginning in middle at the end
Deque: Amortized constant Linear Amortized constant
List: Constant Constant Constant
答案 1 :(得分:45)
deque非常像一个向量:就像vector一样,它是一个支持随机访问元素的序列,在序列末尾不断插入和删除元素,以及线性时间插入和删除元素。中间。
deque与vector不同的主要方式是deque还支持在序列开头的常量时间插入和元素删除。另外,deque没有任何类似于vector的capacity()和reserve()的成员函数,也没有提供与这些成员函数相关的迭代器有效性的任何保证。
以下是来自同一网站的list
摘要:
列表是双向链表。也就是说,它是一个支持前向和后向遍历的序列,以及(开始)(开始)常量时间插入和删除元素的开始或结束,或中间。列表具有重要的属性,即插入和拼接不会使列表元素的迭代器无效,甚至删除也只会使指向被删除元素的迭代器无效。可以更改迭代器的顺序(也就是说,list :: iterator在列表操作之后可能具有与之前不同的前导或后继),但迭代器本身不会失效或被指向不同的元素,除非该失效或突变是明确的。
总之,容器可能有共享例程,但这些例程的时间保证因容器而异。在考虑将哪些容器用于任务时,这一点非常重要:考虑到如何最常用的容器(例如,更多用于搜索而不是插入/删除)需要很长的路要走引导你到正确的容器。
答案 2 :(得分:7)
std::list
基本上是一个双重链接列表。
std::deque
更像是std::vector
。它具有索引的持续访问时间,以及开头和结尾的插入和删除,这提供了与列表截然不同的性能特征。
答案 3 :(得分:4)
没有。 deque仅在前后支持O(1)插入和删除。例如,它可以在具有环绕的向量中实现。由于它也保证了O(1)随机访问,你可以确定它不使用(只是)一个双向链表。
答案 4 :(得分:3)
另一个重要保证是每个不同容器将其数据存储在内存中的方式:
请注意,deque旨在尝试平衡向量和列表的优点,而没有各自的缺点。它是内存受限平台中特别有趣的容器,例如微控制器。
内存存储策略经常被忽略,但是,它通常是为特定应用选择最合适容器的最重要原因之一。
答案 5 :(得分:2)
其他人已经很好地解释了性能差异。我只想补充一点,类似甚至相同的接口在面向对象编程中很常见 - 这是编写面向对象软件的一般方法的一部分。你不应该假设两个类的工作方式相同,只是因为它们实现了相同的接口,你应该假设一匹马像狗一样工作,因为它们都实现了attack()和make_noise()。
答案 6 :(得分:2)
deque
和list
之间的显着差异
对于deque
:
并排存储的项目;
针对从两侧(正面,背面)添加数据进行了优化;
以数字(整数)索引的元素。
可以通过迭代器甚至通过元素的索引进行浏览。
时间访问数据更快。
对于list
“随机”存储在内存中的项目;
只能由迭代器浏览;
针对中间的插入和移除进行了优化。
由于数据的空间位置非常差,因此对数据的时间访问速度较慢,迭代速度很慢。
处理非常大的元素
您还可以检查以下Link,它比较了两个STL容器(使用std :: vector)之间的性能
希望我分享了一些有用的信息。
答案 7 :(得分:2)
我为我的 C++ 课上的学生制作了插图。 这是(松散地)基于(我对)GCC STL 实现中的实现( https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/bits/stl_deque.h 和 https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/bits/stl_list.h)
集合中的元素存储在内存块中。每个块的元素数量取决于元素的大小:元素越大,每个块越少。潜在的希望是,如果无论元素的类型如何,块的大小都相似,那么在大多数情况下这应该有助于分配器。
您有一个列出内存块的数组(在 GCC 实现中称为映射)。除了第一个可能在开头有空间和最后一个可能在结尾有空间之外,所有内存块都已满。地图本身从中心向外填充。与 std::vector
相反,这就是如何在恒定时间内完成两端的插入。与 std:::vector
类似,可以在恒定时间内进行随机访问,但需要两个间接访问而不是一个。与 std::vector
类似且与 std::list
相反,在中间删除或插入元素的成本很高,因为您必须重新组织大部分数据结构。
双向链表可能更常见。每个元素都存储在自己的内存块中,独立于其他元素分配。在每个块中,您都有元素的值和两个指针:一个指向前一个元素,一个指向下一个元素。它使得在列表中的任何位置插入元素变得非常容易,甚至可以将元素的子链从一个列表移动到另一个列表(称为拼接的操作):您只需要更新位于插入点的开始和结束。缺点是要通过索引找到一个元素,您必须遍历指针链,因此随机访问在列表中的元素数量方面具有线性成本。
答案 8 :(得分:1)
这是列表,无序映射的概念验证代码使用,可提供O(1)查找和O(1)精确的LRU维护。需要(未擦除的)迭代器在擦除操作中生存下来。计划在O(1)任意大的软件托管的缓存中使用GPU内存上的CPU指针。向Linux O(1)调度程序点头(每个处理器的LRU <->运行队列)。通过哈希表,unordered_map具有恒定的访问时间。
message.delete()