我正在写一个使用队列的基数排序算法,我希望在我开始向队列添加东西之前,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();
}
}
}
7条答案
按热度按时间vngu2lb81#
很有可能这不是问题。
Deque
是按块分配的,所以您可能只会重新分配几次。您确定这是一个瓶颈了吗?无论如何,标准没有给予'queue'的容器一个访问器,因为这会破坏封装的目的。
如果你真的担心,池分配。这意味着预先分配内存,所以当容器请求内存时,它已经在那里了。我真的不能仔细检查分配器和亲属,这对SO的答案来说是多余的,但是可以查找allocators on Google。
基本上,你可以告诉你的容器从哪里获取内存。通常,这是默认的分配器,它使用new和delete。
Boost提供了一个pool allocator,它将如下所示:
该池预先分配内存,因此在
push()
/pop()
期间不进行实际内存分配。我使用
list
而不是deque
,因为它更简单。通常,deque
上级list
,但是有了分配器,deque
的优势,如缓存性能和分配成本,就不复存在了。因此,list
使用起来简单得多。您也可以使用circular buffer,如下所示:
t0ybt7op2#
您可以尝试使用std::deque来代替...
gab6jxml3#
如果你使用其中一个结构来组成你的队列,它支持“reserve”函数调用,你应该很好。如果这个数据结构不支持你的需要,你可能需要寻找另一个。
话虽如此,您确定这里存在性能问题吗?
雅各布
rqenqsqc4#
听起来你需要一个带有reserve()方法的数据结构,以及从相反的两端进行高效的“push”和“pop”操作。那么,一个环绕在std::vector周围的环形缓冲区怎么样?你可以在构造函数中保留所需的空间,然后在实现中维护“front”和“end”索引,以便将公共接口中的“push”和“pop”操作转换为底层std::vector上的O(1)操作。
vulvrdjw5#
看看这是否有帮助:http://www.cs.sunysb.edu/~skiena/392/programs/queue.c
nsc4cvqm6#
不使用队列,而是使用列表怎么样?
2g32fytz7#
这是一个很老的问题,但我没有看到OP问题的答案:我如何使用带有预分配缓冲区的std::queue呢?
我不知道有哪种解决方案不需要自定义分配器,但是如果你能使用自定义分配器,你就能达到你想要的效果。
概念验证示例代码可在https://github.com/vincetse/allocator上获得,我将在下面剽窃: