C++ priority_queue 底层向量容器容量调整大小

Posted

技术标签:

【中文标题】C++ priority_queue 底层向量容器容量调整大小【英文标题】:C++ priority_queue underlying vector container capacity resize 【发布时间】:2010-09-08 09:40:42 【问题描述】:

我正在使用带有向量的 priority_queue 作为底层容器。但是我希望堆的大小非常大。我知道动态矢量容量调整大小的问题。所以我正在寻找方法来为我的priority_queue 中的底层向量最初分配足够的空间。有什么建议可以实现这一目标吗?

谢谢

【问题讨论】:

【参考方案1】:

stdlib 容器适配器提供了一个“后门”来访问底层容器:容器是一个名为 c 的受保护成员。

因此,您可以从适配器继承以获得对容器的访问权限:

#include <queue>
#include <iostream>

template <class T>
class reservable_priority_queue: public std::priority_queue<T>

public:
    typedef typename std::priority_queue<T>::size_type size_type;
    reservable_priority_queue(size_type capacity = 0)  reserve(capacity); ;
    void reserve(size_type capacity)  this->c.reserve(capacity);  
    size_type capacity() const  return this->c.capacity();  
;

int main()

    reservable_priority_queue<int> q;
    q.reserve(10000);
    std::cout << q.capacity() << '\n';

如果您对从 stdlib 类继承感到难过,请使用私有继承,并通过 using 声明使 priority_queue 的所有方法可访问。

【讨论】:

+1 从理论上讲,我通常会反对从标准容器继承,但在这种情况下,我的工程告诉我这可能是最好的解决方案。 我不喜欢这个解决方案有 2 个原因:1/ 从具有公共非虚拟析构函数的类继承让人感觉很糟糕,非常糟糕,2/ 在 cplusplus 上也没有提到这个后门.com 或 sgi.com/tech/stl ... 我有一种不好的感觉,这是特定于实现的,根本不是标准的。 @Matthiew M. 后门在标准中,因此在技术上是正确的。我同意从容器继承并不是最好的建议...... #define protected public :P @Herbert 这行得通吗?那将是有史以来最好的黑客攻击。 #define private public,您可以访问所有内容。【参考方案2】:

您不能直接访问底层容器来修改容量。但是,您可以将内部使用的容器更改为 std::dequestd::deque 容器可能比向量稍慢(不是大 O 表示法),但它的增长速度要快得多,因为它不需要重新定位所有现有元素。

【讨论】:

我认为最后一句话有错别字。 s/std::queue/std::deque/否?否则我同意。该解决方案使优先级的使用更加安全。双端队列中的元素由块分配。 这不是真的。您可以通过成员c 访问底层容器。它实际上是标准的。 @Elizafox:c 成员是protected,你不能直接从你自己的代码访问这个成员,除非你是从容器继承的,并且你使用自己的类型而不是@987654326 @【参考方案3】:

使用reserve函数:

std::vector<Type>::reserve(size_t size)

示例:

std::vector<int> vec;
vec.reserve(10000);
std::priority_queue<int> q (std::less<int>(), vec);

【讨论】:

我不认为这是一个解决方案。该标准仅要求使用该特定构造函数的第二个参数初始化内部容器。这意味着 std::vector 复制构造函数将被称为传递 vec 作为参数,然后这一切都归结为是否需要 std::vector&lt;T&gt;::vector( std::vector&lt;T&gt; const &amp; ) 来保持相同的容量。该标准不提供该保证。编辑:我刚刚使用 g++ 4.0 进行了测试,并且复制构造函数没有 reserve() 来维持复制向量中的容量。【参考方案4】:

David 对 Alexey 的回答的评论是正确的:向量实现分配副本上保留的内容的可能性不大。因此,要么提供您自己的容器来执行此操作,要么从 priority_queue 继承并提供一些成员来使用底层容器。

【讨论】:

【参考方案5】:

正如 David 所建议的那样,使用 std::deque 可能是一个很好的解决方案。内存块足够小,通常允许您在队列增长时保留大部分内存。 然而,这只是一个更安全的解决方案,而不是一个安全的解决方案。

如果您不太关心效率,您可以使用stlxxl,它是用于超大型数据集的标准模板库的实现。这样,可分配的内存将是您的整个硬盘驱动器(该库还支持多个硬盘驱动器或网络驱动器)。

【讨论】:

以上是关于C++ priority_queue 底层向量容器容量调整大小的主要内容,如果未能解决你的问题,请参考以下文章

C++从青铜到王者第十六篇:STL之priority_queue类的初识和模拟实现

c++容器的底层数据结构

C++初阶第十二篇—stack和queue(stack和queue的常见接口的用法与介绍+priority_queue+容器适配器+仿函数+模拟实现)

C++ STL之priority_queue

C++ 初阶优先级队列(Priority_Queue)底层框架模拟实现

C++ 初阶优先级队列(Priority_Queue)底层框架模拟实现