C++ STL priority_queueコンテナー アダプターを使用して、タイマー キューイング システムを実装したいと考えています。
私の問題は、タイマーを時々キャンセルしたいということですが、最上位のアイテムではないpriority_queue内のアイテムを簡単に削除できるインターフェイスがありません。
助言がありますか?。
ご協力ありがとうございました。
C++ STL priority_queueコンテナー アダプターを使用して、タイマー キューイング システムを実装したいと考えています。
私の問題は、タイマーを時々キャンセルしたいということですが、最上位のアイテムではないpriority_queue内のアイテムを簡単に削除できるインターフェイスがありません。
助言がありますか?。
ご協力ありがとうございました。
まったく同じシナリオが一度あり、次のことを行いました。
std::priority_queue
ソートする時間と a へのインデックスのみが含まれていましたstd::vector<Handler>
(私の場合Handler
は でしたがboost::function
、インターフェイスまたは関数へのポインターである可能性もあります)boost::function
callclear()
の場合、ポインターを使用する場合はゼロに設定します)1フリー インデックスをすばやく見つけるために、個別std::stack
のインデックスを使用しました。タイマーを追加し、そのスタックが空である場合、ベクターの最後に追加します。それ以外の場合は、トップ インデックスをポップして使用します。
2フリーインデックススタックにインデックスをpushするときのポイントはこちら
特にタイマーコールバックでタイマーを追加またはキャンセルする必要がある場合は、全体がややこしく、エラーが発生しやすくなります。上記のキャンセル タイマー クラスへのリンクは次のとおりです。このコードはパブリック ドメインです。
残念ながら、 STLpriority_queue
はそのような機能を提供していません。独自のヒープ クラスを作成できます (それほど難しくありません)。std::xxx_heap
次のような汚いトリックで関数を使用することもできます。
delete_heap(iterator to_delete, iterator heap_begin, iterator heap_end)
{
to_delete->key = something that would compare less to everything; // make sure it gets to the top in the next step
std::push_heap(heap_begin, to_delete+1);
std::pop_heap(heap_begin, heap_end);
}
これでO(log n)
削除できます。
他のいくつかの回答が述べているにもかかわらずpriority_queue
、コンテナは と呼ばれる保護されたメンバーとして公開されているため、 を含む任意の標準コンテナ アダプタの基になるコンテナにアクセスすることができますc
。インターフェイスを継承して拡張するか、このpriority_queue
ようなダーティ トリックを使用して一時的に法線にアクセスすることができます。priority_queue
私の問題は、タイマーを時々キャンセルしたいということですが、最上位のアイテムではないpriority_queue内のアイテムを簡単に削除できるインターフェイスがありません。
タイマーのキャンセルが頻繁に発生する場合は、別の構造を使用する必要があります。std::map もそれほど悪くはありませんが、delete_min のコストは高くなります。
タイマーのキャンセルがめったに起こらない場合は、要素を削除済みとしてマークする (および ::pop の間は無視する) とうまくいくかもしれません。
STL の priority_queue コンテナーは、最上位のアイテムのみにアクセスできるように特別に設計されているため、最上位以外のアイテムを削除できるようにする必要がある場合は、使用する別のクラスを見つける必要があります。
私は同じ要件を持っていました。コンテナーを自由に変更できる場合、この問題を解決できるのはstd::set (重複は許可されません) またはstd::multisetです。
どちらも順序付けられており、コンテナー サイズで要素対数を消去できます (詳細については、ドキュメントを参照してください)。マルチ セットの削除については、こちらを参照してください。
決定する前に、 std::set と std::priority_queueの違いを確認してください。