我在有效STL中注意到
向量是默认情况下应使用的序列类型。
什么意思 似乎无视效率vector
无能为力。
有人可以给我提供vector
一个不可行的方案,但list
必须使用的方案吗?
我在有效STL中注意到
向量是默认情况下应使用的序列类型。
什么意思 似乎无视效率vector
无能为力。
有人可以给我提供vector
一个不可行的方案,但list
必须使用的方案吗?
Answers:
list
具有push_front
向量:
清单:
通常,当您不在乎所使用的顺序容器类型时,可以使用vector,但是如果要在容器中除末尾以外的任何位置进行多次插入或删除操作,您将需要使用清单。或者,如果您需要随机访问,那么您将需要向量,而不是列表。除此之外,在某些情况下自然会根据您的应用程序需要一个或另一个,但是总的来说,这些都是很好的准则。
reserve()
将其减少为O(1)。将新项目添加到列表(即不进行拼接)将执行O(n)个免费商店分配。
list
当您擦除元素时会释放内存,但vector
不会。vector
减小大小时,A 不会减少其容量,除非您使用swap()
技巧。
这里的大多数答案都遗漏了一个重要的细节:为什么?
您想在容器中保留什么?
如果它是的集合int
,则std::list
在每种情况下都将丢失,无论是否可以重新分配,都只能从前面删除,以此类推。列表的遍历速度较慢,每次插入都需要您与分配器进行交互。准备一个list<int>
跳动的例子是非常困难的vector<int>
。即使这样deque<int>
也可能更好或更接近,而不是仅仅依靠列表的使用,这将增加内存开销。
但是,如果您要处理的是大块丑陋的数据-其中很少-您不想在插入时进行总体分配,并且由于重新分配而进行的复制将是一场灾难-那么,也许可以list<UglyBlob>
比vector<UglyBlob>
。
不过,如果您切换到vector<UglyBlob*>
甚至vector<shared_ptr<UglyBlob> >
再次,则-列表会落后。
因此,访问模式,目标元素数量等仍然会影响比较,但是在我看来-元素大小-复制成本等。
list<T>
这样的可能性,以splice
在O(1) 。如果需要恒定时间的拼接,列表也可能是选择的结构;)
UglyBlob
-即使只有几柱部件很容易被复制昂贵的对象,因此,重新分配将成本。另外:不要忽略空间开销,vector
几十个大小的保持对象的指数增长可能会导致(如果不能reserve
提前)。
vector<smart_ptr<Large>>
vs。list<Large>
我想说的是,如果您需要随机访问元素,这vector
是有道理的。如果您不需要随机访问,则list
看起来更简单,并且应具有相同的性能。
std :: list的一种特殊功能是拼接(将部分或整个列表链接或移动到另一个列表中)。
或者,如果您的内容复制非常昂贵。在这种情况下,例如,用列表对集合进行排序可能会更便宜。
还要注意,如果集合很小(并且内容复制并不特别昂贵),即使您在任何地方插入和删除向量,向量也可能仍然胜过列表。列表会分别分配每个节点,这可能比移动一些简单的对象要贵得多。
我认为没有非常严格的规定。这取决于您最想对容器执行什么操作,以及容器的大小和所包含的类型。向量通常胜过一个列表,因为它将其内容分配为单个连续的块(它基本上是一个动态分配的数组,在大多数情况下,数组是保存一堆东西的最有效方法)。
list::size
不一定是固定时间。参见stackoverflow.com/questions/228908/is-listsize-really-on和gcc.gnu.org/ml/libstdc++/2005-11/msg00219.html
splice
,不同列表之间的顺序被指定为线性复杂度,size
并且特别恒定。因此,为了适应那些反复进行的新手,size
对于STL或任何“兼容”容器时期,一整类算法都无法解决。
好吧,我班的学生们似乎无法向我解释什么时候使用向量更有效,但是当他们建议我使用列表时,他们看起来很高兴。
这就是我的理解
列表:每个项目都包含下一个或上一个元素的地址,因此,使用此功能,您可以将这些项目随机化,即使它们没有排序,顺序也不会改变:如果内存碎片化,这将非常有效。但这还有另一个很大的优点:您可以轻松地插入/删除项目,因为您唯一需要做的就是更改一些指针。缺点:要读取随机的单个项目,您必须从一个项目跳到另一个项目,直到找到正确的地址。
向量:使用向量时,内存的组织方式更像常规数组:第n个项目存储在第(n-1)个项目之后和第(n + 1)个项目之前。为什么比列表更好?因为它允许快速随机访问。方法如下:如果您知道向量中某个项目的大小,并且它们在内存中是连续的,则可以轻松地预测第n个项目在哪里;您无需浏览列表中的所有项目即可阅读所需的内容,而使用vector则可以直接阅读,而无需阅读列表。另一方面,修改向量数组或更改值的速度要慢得多。
列表更适合跟踪可在内存中添加/删除的对象。当您要从大量单个项目访问元素时,向量更合适。
我不知道如何优化列表,但是您必须知道,如果要快速读取访问,则应该使用向量,因为STL固定列表的能力非常好,读取访问的速度不会比向量快。
vector
造成改变其大小可能会很慢?然后同意,但在reserve()
可以使用的情况下,可以避免这些问题。
当序列中间有很多插入或删除时。例如内存管理器。
要在容器之间移动对象时,可以使用list::splice
。
例如,图分区算法可以在越来越多的容器中递归地划分恒定数量的对象。对象应初始化一次,并始终保留在内存中的相同位置。通过重新链接重新排列它们比通过重新分配要快得多。
编辑:随着库准备实现C ++ 0x,将子序列拼接到列表中的一般情况随着序列的长度而变得线性复杂。这是因为splice
(现在)需要遍历该序列以计算其中的元素数量。(因为列表需要记录其大小。)简单地对列表进行计数和重新链接仍然比任何其他方法都要快,并且拼接整个列表或单个元素是具有恒定复杂性的特殊情况。但是,如果要拼接的序列很长,则可能需要挖掘一个更好的,老式的,不兼容的容器。
对于vector和list,突出的主要区别如下:
向量
向量将其元素存储在连续内存中。因此,可以在向量内部进行随机访问,这意味着访问向量的元素非常快,因为我们可以简单地将基地址与项索引相乘以访问该元素。实际上,为此仅需要O(1)或恒定时间。
由于向量基本上是包装一个数组,因此,每次将一个元素插入向量(动态数组)时,它都必须通过查找新的连续内存块来容纳新元素来调整自身大小,而这是耗时的。
它不消耗额外的内存来存储指向其中其他元素的任何指针。
清单
列表将其元素存储在非连续内存中。因此,列表内的随机访问是不可能的,这意味着要访问其元素,我们必须使用指针并遍历相对于向量而言较慢的列表。这需要O(n)或比O(1)慢的线性时间。
由于列表使用非连续内存,因此将元素插入列表内所需的时间比其向量对应对象的效率高得多,因为可以避免重新分配内存。
它消耗额外的内存来在特定元素之前和之后存储指向该元素的指针。
因此,请牢记这些差异,我们通常会考虑内存,频繁的随机访问和插入来确定给定场景中向量与列表的优胜者。
列表是双链表,因此很容易插入和删除元素。我们只需要更改几个指针,而在向量中,如果我们想在中间插入一个元素,则其后的每个元素都必须移动一个索引。同样,如果向量的大小已满,则必须首先增加其大小。因此,这是一项昂贵的操作。因此,在这种情况下,无论何时需要更频繁地执行插入和删除操作,都应使用列表。