卑劣ですが、必要なことを行うために の機能をオーバーライドできるはずstd::priority_queue
です。これは、私が行ったいくつかのテストでうまくいくようです:
template<typename T>
class fixed_priority_queue : public std::priority_queue<T>
{
public:
fixed_priority_queue(unsigned int size) : fixed_size(size) {}
void push(const T& x)
{
// If we've reached capacity, find the FIRST smallest object and replace
// it if 'x' is larger
if(this->size() == fixed_size)
{
// 'c' is the container used by priority_queue and is a protected member.
auto beg = c.begin(); auto end = c.end();
auto min = std::min_element(beg, end);
if(x > *min)
{
*min = x;
// Re-make the heap, since we may have just invalidated it.
std::make_heap(beg, end);
}
}
// Otherwise just push the new item.
else
{
priority_queue::push(x);
}
}
private:
fixed_priority_queue() {} // Construct with size only.
const unsigned int fixed_size;
// Prevent heap allocation
void * operator new (size_t);
void * operator new[] (size_t);
void operator delete (void *);
void operator delete[] (void*);
};
ここで何が起こっているのですか?
std::priority_queue
クラスを拡張する
- メソッドをオーバーライドし、
priority_queue::push()
最下位のアイテムを新しいアイテムに交換します
- デフォルトのコンストラクターはプライベートで、サイズのない構築はありません
- STL コンテナには仮想デストラクタがないため、ヒープの割り当てを制限します。
使用するには:
const unsigned int LIMIT = 20;
fixed_priority_queue<int> fooQueue(LIMIT);
// Testing.
for(int i=0; i<40; i++)
fooQueue.push(rand());
for(int i=0; i<LIMIT; i++)
{
printf("%i\n", fooQueue.top());
fooQueue.pop();
}
ここで何が悪いのですか?
- これらのキューをヒープ上に安全に作成することはできないため、大きなキューは問題外になる可能性があります。あなたが言及したように、とにかくスタック上で問題ないはずです(オブジェクトによって異なります)。私はおそらく大きなキューを避けるでしょう...
- ここでのパフォーマンスのヒットはわかりません。
priority_queue
基礎となるコンテナーの呼び出しmake_heap
(デフォルトでは std::vector)。通常どのくらいの頻度で呼び出されるかはわかりませんが、キューがいっぱいの場合は頻繁に呼び出します。内でも呼ばれると思いますpriority_queue::push()
か?
- おそらく他にもたくさんあるので、読者からの建設的なフィードバックと編集を歓迎します:)
少なくとも興味深いものではないにしても、これが役立つことを願っています。