数组、向量、列表

发布于 2024-08-15 01:34:56 字数 492 浏览 2 评论 0原文

我正在维护一个包含 10 个条目的固定长度表。每个项目都是由 4 个字段组成的结构。将有插入、更新和删除操作,由数字位置指定。我想知道哪个是用于维护此信息表的最佳数据结构:

  1. 数组 - 由于移位,插入/删除需要线性时间;更新需要恒定的时间;没有空间用于指针;使用 [] 访问项目速度更快。

  2. stl 向量 - 由于移位,插入/删除需要线性时间;更新需要恒定的时间;没有空间用于指针;访问项目比数组慢,因为它是对运算符 [] 和链表的调用。

  3. stl list - 插入和删除需要线性时间,因为您需要在应用插入/删除之前迭代到特定位置;指针需要额外的空间;访问项目比数组慢,因为它是链表线性遍历。

现在,我的选择是使用数组。有道理吗?或者我错过了什么?

哪个更快:遍历列表,然后插入节点或移动数组中的项目以产生空位置,然后在该位置插入项目?

衡量这种性能的最佳方法是什么?我可以只显示操作前后的时间戳吗?

I am maintaining a fixed-length table of 10 entries. Each item is a structure of like 4 fields. There will be insert, update and delete operations, specified by numeric position. I am wondering which is the best data structure to use to maintain this table of information:

  1. array - insert/delete takes linear time due to shifting; update takes constant time; no space is used for pointers; accessing an item using [] is faster.

  2. stl vector - insert/delete takes linear time due to shifting; update takes constant time; no space is used for pointers; accessing an item is slower than an array since it is a call to operator[] and a linked list .

  3. stl list - insert and delete takes linear time since you need to iterate to a specific position before applying the insert/delete; additional space is needed for pointers; accessing an item is slower than an array since it is a linked list linear traversal.

Right now, my choice is to use an array. Is it justifiable? Or did I miss something?

Which is faster: traversing a list, then inserting a node or shifting items in an array to produce an empty position then inserting the item in that position?

What is the best way to measure this performance? Can I just display the timestamp before and after the operations?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

苯莒 2024-08-22 01:34:56

使用STL矢量。它提供了与list同样丰富的接口,并消除了管理数组所需内存的麻烦。

您必须非常努力地暴露 operator[] 的性能成本 - 它通常会被内联。

我没有任何数字可以给您,但我记得读过性能分析,其中描述了 vectorlist 即使对于插入和删除也更快(当然在一定的尺寸下)。事实是,我们使用的这些处理器非常快 - 如果您的向量适合 L2 缓存,那么它的运行速度会非常非常快。另一方面,列表必须管理堆对象,这会杀死你的 L2。

Use STL vector. It provides an equally rich interface as list and removes the pain of managing memory that arrays require.

You will have to try very hard to expose the performance cost of operator[] - it usually gets inlined.

I do not have any number to give you, but I remember reading performance analysis that described how vector<int> was faster than list<int> even for inserts and deletes (under a certain size of course). The truth of the matter is that these processors we use are very fast - and if your vector fits in L2 cache, then it's going to go really really fast. Lists on the other hand have to manage heap objects that will kill your L2.

烙印 2024-08-22 01:34:56

过早的优化是万恶之源。

根据您的帖子,我想说没有理由让您在这里选择基于性能的数据结构。当且仅当性能测试表明这是一个问题时,选择最方便的并返回更改它。

Premature optimization is the root of all evil.

Based on your post, I'd say there's no reason to make your choice of data structure here a performance based one. Pick whatever is most convenient and return to change it if and only if performance testing demonstrates it's a problem.

无妨# 2024-08-22 01:34:56

确实值得花一些时间来理解列表和向量之间的根本区别。
两者之间最显着的区别是它们存储元素和跟踪元素的方式。

- 列表-

列表包含存储了上一个和下一个元素的地址的元素。这意味着无论列表大小如何,您都可以以恒定的速度 O(1) 在列表中的任何位置插入或删除元素。您还可以在任意位置以恒定速度拼接(插入另一个列表)到现有列表中。原因是列表只需要更改我们要插入列表中的元素的两个指针(前一个和下一个)。

如果您需要随机访问,列表并不好。因此,如果计划访问列表中的第 n 个元素,则必须逐个遍历列表 - O(n) 速度

- 向量 -

向量按顺序包含元素,就像数组一样。这对于随机访问来说非常方便。访问向量中的“第 n”个元素是一个简单的指针计算(速度为 O(1))。然而,向向量添加元素是不同的。如果想要在向量中间添加一个元素,则必须重新分配该元素之后的所有元素,以便为新条目腾出空间。速度将取决于向量大小和新元素的位置。最坏的情况是在向量的位置 2 处插入一个元素,最好的情况是追加一个新元素。因此 - 插入的速度为 O(n),其中“n”是需要移动的元素数量 - 不一定是向量的大小。

还有其他涉及内存要求等方面的差异,但是了解列表和向量实际工作原理的这些基本原理确实值得花一些时间。

一如既往……“过早的优化是万恶之源”,因此首先考虑什么更方便,让事情完全按照您想要的方式运行,然后进行优化。对于您提到的 10 个条目 - 您使用什么并不重要 - 无论您使用什么方法,您都永远无法看到任何类型的性能差异。

It is really worth investing some time in understanding the fundamental differences between lists and vectors.
The most significant difference between the two is the way they store elements and keep track of them.

- Lists -

List contains elements which have the address of a previous and next element stored in them. This means that you can INSERT or DELETE an element anywhere in the list with constant speed O(1) regardless of the list size. You also splice (insert another list) into the existing list anywhere with constant speed as well. The reason is that list only needs to change two pointers (the previous and next) for the element we are inserting into the list.

Lists are not good if you need random access. So if one plans to access nth element in the list - one has to traverse the list one by one - O(n) speed

- Vectors -

Vector contains elements in sequence, just like an array. This is very convenient for random access. Accessing the "nth" element in a vector is a simple pointer calculation (O(1) speed). Adding elements to a vector is, however, different. If one wants to add an element in the middle of a vector - all the elements that come after that element will have to be re allocated down to make room for the new entry. The speed will depend on the vector size and on the position of the new element. The worst case scenario is inserting an element at position 2 in a vector, the best one is appending a new element. Therefore - insert works with speed O(n), where "n" is the number of elements that need to be moved - not necessarily the size of a vector.

There are other differences that involve memory requirements etc., but understanding these basic principles of how lists and vectors actually work is really worth spending some time on.

As always ... "Premature optimization is the root of all evil" so first consider what is more convenient and make things work exactly the way you want them, then optimize. For 10 entries that you mention - it really does not matter what you use - you will never be able to see any kind of performance difference whatever method you use.

比忠 2024-08-22 01:34:56

更喜欢 std::vector 而不是数组。矢量的一些优点是:

  • 当大小增加时,它们从可用空间分配内存。
  • 它们不是伪装的指针。
  • 它们可以增加/减少运行时间的大小。
  • 他们可以使用at()进行范围检查。
  • 向量知道它的大小,因此您不必计算元素数。

使用向量最令人信服的原因是它使您免于显式内存管理,并且不会泄漏内存。向量会跟踪它用来存储其元素的内存。当向量需要更多内存来存储元素时,它会分配更多内存;当向量超出范围时,它会释放该内存。因此,用户无需关心向量元素的内存分配和释放。

Prefer an std::vector over and array. Some advantages of vector are:

  • They allocate memory from the free space when increasing in size.
  • They are NOT a pointer in disguise.
  • They can increase/decrease in size run-time.
  • They can do range checking using at().
  • A vector knows its size, so you don't have to count elements.

The most compelling reason to use a vector is that it frees you from explicit memory management, and it does not leak memory. A vector keeps track of the memory it uses to store its elements. When a vector needs more memory for elements, it allocates more; when a vector goes out of scope, it frees that memory. Therefore, the user need not be concerned with the allocation and deallocation of memory for vector elements.

何其悲哀 2024-08-22 01:34:56

您正在做出不应该做出的假设,例如“访问一个项目比数组慢,因为它是对operator[]的调用。”我可以理解其背后的逻辑,但在我们对其进行分析之前,你和我都无法知道。

如果这样做,您会发现当优化打开时根本没有任何开销。编译器内联函数调用。内存性能存在差异。数组是静态分配的,而向量是动态分配的。列表为每个节点分配,如果不小心,可能会限制缓存。

一些解决方案是让向量从堆栈中分配,并为列表提供一个池分配器,以便节点可以放入缓存中。

因此,您不必担心不受支持的声明,而应该担心使您的设计尽可能简洁。那么,哪个更有意义呢?数组、向量还是列表?我不知道你想做什么,所以无法回答你。

“默认”容器往往是一个向量。有时数组也是完全可以接受的。

You're making assumptions you shouldn't be making, such as "accessing an item is slower than an array since it is a call to operator[]." I can understand the logic behind it, but you nor I can know until we profile it.

If you do, you'll find there is no overhead at all, when optimizations are turned on. The compiler inlines the function calls. There is a difference in memory performance. An array is statically allocated, while a vector dynamically allocates. A list allocates per node, which can throttle cache if you're not careful.

Some solutions are to have the vector allocate from the stack, and have a pool allocator for a list, so that the nodes can fit into cache.

So rather than worry about unsupported claims, you should worry about making your design as clean as possible. So, which makes more sense? An array, vector, or list? I don't know what you're trying to do so I can't answer you.

The "default" container tends to be a vector. Sometimes an array is perfectly acceptable too.

尐偏执 2024-08-22 01:34:56

首先是一些注意事项:

关于选择数据结构的一个好的经验法则:通常,如果您检查了所有可能性并确定数组是您的最佳选择,请重新开始。你做了一件非常错误的事。

STL 列表不支持 operator[],如果支持,它会比索引数组慢的原因与函数调用的开销无关。

话虽这么说,矢量显然是赢家。对operator[]的调用基本上可以忽略不计,因为向量的内容保证在内存中是连续的。它支持 insert()erase() 操作,如果您使用数组,您必须自己编写这些操作。基本上,它可以归结为一个事实:向量本质上是一个升级的数组,它已经支持您需要的所有操作。

First a couple of notes:

A good rule of thumb about selecting data structures: Generally, if you examined all the possibilities and determined that an array is your best choice, start over. You did something very wrong.

STL lists don't support operator[], and if they did the reason that it would be slower than indexing an array has nothing to do with the overhead of a function call.

Those things being said, vector is the clear winner here. The call to operator[] is essentially negligible since the contents of a vector are guaranteed to be contiguous in memory. It supports insert() and erase() operations which you would essntially have to write yourself if you used an array. Basically it boils down to the fact that a vector is essentially an upgraded array which already supports all the operations you need.

2024-08-22 01:34:56

我正在维护一个包含 10 个条目的固定长度表。每个项目都是一个
类似4个字段的结构。会有插入、更新、删除
操作,由数字位置指定。我想知道哪个是
用于维护此信息表的最佳数据结构:

根据此描述,列表似乎可能是更好的选择,因为在数据结构中间插入和删除时其 O(1)。不幸的是,当使用列表进行插入和删除时,您不能像数组/向量那样使用数字位置。这种困境导致了一系列问题,可用于初步决定哪种结构最适合使用。如果测试清楚地表明其选择是错误的,则可以稍后更改此结构。

您需要问的问题有三个。第一个是相对于随机读取,您计划在中间进行删除/插入的频率。第二个是与迭代器相比使用数字位置的重要性。最后,结构的顺序很重要。

如果第一个问题的答案是随机读取将比向量/数组更普遍,可能会工作得很好。请注意,即使使用了operator[]表示法,迭代数据结构也不被视为随机读取。对于第二个问题,如果您绝对需要数字位置,则需要向量/数组,即使这可能会导致性能下降。稍后的测试可能表明,相对于更容易的数字位置编码,这种性能影响可以忽略不计。最后,如果顺序不重要,您可以使用 O(1) 算法在向量/数组中插入和删除。下面显示了示例算法。

template <class T>
void erase(vector<T> & vect, int index) //note: vector cannot be const since you are changing vector
{
  vect[index]= vect.back();//move the item in the back to the index
  vect.pop_back(); //delete the item in the back
}

template <class T>
void insert(vector<T> & vect, int index, T value) //note: vector cannot be const since you are changing vector
{
  vect.push_back(vect[index]);//insert the item at index to the back of the vector
  vect[index] = value; //replace the item at index with value
}

I am maintaining a fixed-length table of 10 entries. Each item is a
structure of like 4 fields. There will be insert, update and delete
operations, specified by numeric position. I am wondering which is the
best data structure to use to maintain this table of information:

Based on this description it seems like list might be the better choice since its O(1) when inserting and deleting in the middle of the data structure. Unfortunately you cannot use numeric positions when using lists to do inserts and deletes like you can for arrays/vectors. This dilemma leads to a slew of questions which can be used to make an initial decision of which structure may be best to use. This structure can later be changed if testing clearly shows its the wrong choice.

The questions you need to ask are three fold. The first is how often are you planning on doing deletes/inserts in the middle relative to random reads. The second is how important is using a numeric position compared to an iterator. Finally, is order in your structure important.

If the answer to the first question is random reads will be more prevalent than a vector/array will probably work well. Note iterating through a data structure is not considered a random read even if the operator[] notation is used. For the second question, if you absolutely require numeric position than a vector/array will be required even though this may lead to a performance hit. Later testing may show this performance hit is negligible relative to the easier coding with numerical positions. Finally if order is unimportant you can insert and delete in a vector/array with an O(1) algorithm. A sample algorithm is shown below.

template <class T>
void erase(vector<T> & vect, int index) //note: vector cannot be const since you are changing vector
{
  vect[index]= vect.back();//move the item in the back to the index
  vect.pop_back(); //delete the item in the back
}

template <class T>
void insert(vector<T> & vect, int index, T value) //note: vector cannot be const since you are changing vector
{
  vect.push_back(vect[index]);//insert the item at index to the back of the vector
  vect[index] = value; //replace the item at index with value
}
爱她像谁 2024-08-22 01:34:56

我相信,如果需要在开始或中间使用列表中进行更多插入/删除(内部双链接),如果需要随机访问数据并添加到最后一个元素使用数组(向量具有动态分配,但如果您需要更多操作如排序、调整大小等使用向量)

I Believe it's as per your need if one needs more insert/to delete in starting or middle use list(doubly-linked internally) if one needs to access data randomly and addition to last element use array ( vector have dynamic allocation but if you require more operation as a sort, resize, etc use vector)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文