std::queue<T, list<T> >::size() 在 O(n) 中很慢?
std::queue<T, list<T> >::size() is slow in O(n)?
我在使用队列的代码中遇到了意想不到的性能行为。我意识到当队列中有更多元素时,性能会下降。结果表明,size()
方法的使用是原因。下面是显示问题的一些代码:
#include <queue>
#include <list>
#include <iostream>
#include "Stopwatch.h"
using namespace std;
struct BigStruct
{
int x[100];
};
int main()
{
CStopwatch queueTestSw;
typedef BigStruct QueueElementType;
typedef std::queue<QueueElementType, std::list<QueueElementType> > QueueType;
//typedef std::queue<QueueElementType > QueueType; //no surprise, this queue is fast and constant
QueueType m_queue;
for (int i=0;i<22000;i++)
m_queue.push(QueueElementType());
CStopwatch sw;
sw.Start();
int dummy;
while (!m_queue.empty())
{
//remove 1000 elements:
for (int i=0;i<1000;i++)
{
m_queue.pop();
}
//call size() 1000 times and see how long it takes
sw = CStopwatch();
sw.Start();
for (int i=0;i<1000;i++)
{
if (m_queue.size() == 123456)
{
dummy++;
}
}
std::cout << m_queue.size() << " items left. time: " << sw.GetElapsedTimeInSeconds() << std::endl;
}
return dummy;
}
其中CStopwatch
是使用clock_gettime(CLOCK_REALTIME, ..)
的类。结果是:
21000 items left. time: 1.08725
20000 items left. time: 0.968897
19000 items left. time: 0.818259
18000 items left. time: 0.71495
17000 items left. time: 0.583725
16000 items left. time: 0.497451
15000 items left. time: 0.422712
14000 items left. time: 0.352949
13000 items left. time: 0.30133
12000 items left. time: 0.227588
11000 items left. time: 0.178617
10000 items left. time: 0.124512
9000 items left. time: 0.0893425
8000 items left. time: 0.0639174
7000 items left. time: 0.0476441
6000 items left. time: 0.033177
5000 items left. time: 0.0276136
4000 items left. time: 0.022112
3000 items left. time: 0.0163013
2000 items left. time: 0.0101932
1000 items left. time: 0.00506138
这似乎与http://www.cplusplus.com/reference/stl/queue/size/:
复杂性:常数。
如果结构体更大,问题会更严重。我使用的是GCC 4.3.2.
你能解释一下吗?有没有办法用列表来解决这个问题?
(请注意,我需要使用列表作为队列的底层容器,因为我需要恒定时间的插入复杂度。)
queue
是一个容器适配器,因此您必须理解复杂性描述可能仅指适配器本身所做的工作(这实际上是常量,即只是将调用传递给底层容器)。
size()
调用底层容器的size()
函数。对于list
,在c++ 98/03中复杂度为0 (n),在c++ 11中复杂度为0(1)。
您的queue
使用list
容器,而不是deque
默认:
typedef std::queue<QueueElementType, std::list<QueueElementType> > QueueType;
您不应该对size需要O(n)感到惊讶,因为这是c++ 11之前的list
容器的完全有效实现。标准的前一个版本没有保证列表的size
成员函数的复杂性。
如果您将代码更改为:
typedef std::queue<QueueElementType, std::deque<QueueElementType> > QueueType;
您将看到您想要的行为(O(1)大小复杂度)。
补充Michael的回答:您使用std::list
作为队列容器,因此size()
方法取决于您的std::list实现的大小。如果你在同一个网站上查找,你会发现http://www.cplusplus.com/reference/stl/list/size/,一些实现的复杂性是恒定的,而另一些是线性的。如果您需要恒定的插入和大小,那么您需要不同的数据结构或更好的std::list
实现。
相关文章:
- 请解释这句话(cout<<1+int((a<b)^((b-a)&1) )<<endl
- 呼叫运营商<<临时
- 如何防止clang格式在流运算符调用之间添加换行符<<
- <<操作员在下面的行中工作
- EASTL矢量<向量<int>>连续的
- C - 创建矢量&lt; vector&lt; double&gt;&gt;矩阵具有分配而不是inizializ
- 为什么将此对向量&lt; map&lt; int,int&gt;&gt;中的地图进行更新.失败
- C :对矢量进行排序&lt; struct&gt;(结构有2个整数)基于结构的整数之一
- 明确的专业化“ CheckIntmap&lt;&gt;”实例化
- 什么是模板&lt;&gt;inline bla bla
- 编辑C Qlist&lt; object*&gt; gt;QML代码和一些QML警告中的模型
- eigen :: llt&lt;eigen :: matrixxd&gt;具有不完整的类型
- 错误,包括&lt; ctype&gt;在原子上使用C 11
- std::vector<;uint8_t>;当C++11/14启用时,手动复制而不是调用memcpy
- 如何加入向量&lt; int&gt;到C 中的单个INT
- 是std :: set&lt; std :: future&gt;不可能存在
- 是numeric_limits&lt; int&gt; :: is_modulo从逻辑上矛盾
- opencv 2.4.7在iOS错误背景_segm.hpp #include&lt; list&gt;未找到
- 在修改列表后,std :: list&lt; t&gt; :: end()的值是否会更改
- ///<评论></评论>在Visual Studio中