我正在使用队列编写基数排序算法,我希望在开始向队列添加内容之前让STL队列分配空间,这样我就可以避免不断的动态调整大小操作。
即使这不存在,我想要一些具有......的效果的东西。
queue<int> qs(N);
for(int i=0;i<N;++i)
qs.push(rand());
以这种方式在循环期间不会动态分配任何内存。
有问题的实际代码......
void radix_sort()
{
// Biggest number?
int max=-1;
for(int i=0;i<N;++i)
if(a[i]>max)
max = a[i];
// How many digits in it
int maxdigits=1;
while(max /= 10) maxdigits++;
// Create some buckets.
deque<int> b[10];
for(int i=0;i<10;++i)
b[i] = deque<int>(N);
int div=1;
// Radix Sort by digits
for(int d=1;d<=maxdigits;++d)
{
if(d>1)
div*=10;
// Queue
for(int i=0;i<N;++i)
b[ (a[i]/div) % 10 ].push_front(a[i]);
// Dequeue
int k=0;
for(int q=0;q<10;++q)
while(b[q].size() > 0)
{
a[k++] = b[q].back();
b[q].pop_back();
}
}
}
答案 0 :(得分:26)
这可能不是问题。无论如何Deque
分配,所以你可能只会重新分配几次。你确定这是一个瓶颈吗?
无论如何,标准没有提供`queue'容器的访问器,因为这会破坏封装的目的。
如果你真的很担心,游泳池分配。这意味着预先预先分配内存,所以当容器请求内存时,它已经存在。我不能真的去讨论分配器和亲属,这对于一个SO答案来说太过分了,但是查找allocators on Google。
基本上,你可以告诉容器从哪里获取内存。通常,这是默认的分配器,它使用new和delete。
Boost提供pool allocator,它会是这样的:
#include <list>
#include <queue>
// pool
#include <boost/pool/pool_alloc.hpp>
// helpful typedef's
typedef boost::fast_pool_allocator<int> BoostIntAllocator;
typedef boost::singleton_pool<boost::fast_pool_allocator_tag, sizeof(int)> BoostIntAllocatorPool;
int main(void)
{
// specify the list as the underlying container, and inside of that,
// specify fast_pool_allocator as the allocator. by default, it preallocates
// 32 elements.
std::queue<int, std::list<int, BoostIntAllocator > > q;
/* No memory allocations take place below this comment */
for (int i = 0; i < 31; ++i)
{
q.push(i);
}
/* End no allocation */
// normally, the memory used by the singleton will
// not be free'd until after the program is complete,
// but we can purge the memory manually, if desired:
BoostIntAllocatorPool::purge_memory();
};
池预先分配内存,因此在push()
/ pop()
期间不会进行实际的内存分配。
我使用list
代替deque
,因为它更简单。通常情况下,deque
is superior to a list
,但有一个分配器,使deque
有利的事情,如缓存性能和分配成本,不再存在。因此,list
更易于使用。
您还可以使用circular buffer,例如:
#include <queue>
// ring
#include <boost/circular_buffer.hpp>
int main(void)
{
// use a circular buffer as the container. no allocations take place,
// but be sure not to overflow it. this will allocate room for 32 elements.
std::queue<int, boost::circular_buffer<int> > q(boost::circular_buffer<int>(32));
/* No memory allocations take place below this comment */
for (int i = 0; i < 31; ++i)
{
q.push(i);
}
/* End no allocation */
};
答案 1 :(得分:4)
您可以尝试使用std :: deque而不是......
答案 2 :(得分:3)
如果您使用其中一个结构来组成支持“保留”函数调用的队列,那么您应该很好。如果此数据结构不支持您的需求,您可能需要查找另一个。
话虽如此,你确定这里存在性能问题吗?
雅各
答案 3 :(得分:2)
听起来你需要一个带有reserve()方法的数据结构,以及来自两端的高效“推”和“弹出”操作。如何将环形缓冲区包裹在std :: vector中?您可以在构造函数中保留()所需的空间,然后在实现中维护“前”和“结束”索引,将公共接口中的“push”和“pop”操作转换为底层std上的O(1)操作::矢量。
答案 4 :(得分:1)
而不是队列,如何使用列表代替?
答案 5 :(得分:1)