如何从列表中删除具有相应优先级队列的元素?

时间:2013-02-14 06:25:55

标签: c++ list priority-queue

我有一个std ::对象列表,比如兔子。每只兔子有两个属性:身份证和体重。在这个列表中,兔子是ID的顺序。 然后我使用std :: priority_queue按重量顺序存储指向该兔子列表的指针。

现在我将使用此priority_queue删除priority_queue和原始列表中最轻的N只兔子。      问题 是:如何在原始列表中删除?
示例代码:

#include <queue>
using namespace std;
list<Rabbit> rabbitArmy; 
priority_queue<Rabbit, vector<Rabbit*>, CompareWeight> rabbitSortByWeight;


for (int i = 0; i < 999; i++) {

    .....

    // each rabbit has different ID and Weight, codes omitted
    Rabbit rabbit(randomID, randomWeight); 
    rabbitArmy.push_back(rabbit);
    rabbitSortByWeight.push(&rabbitArmy.back());
}


// Now I'll delete N lightest rabbits in the priority_queue
for (int i = 0; i < N; i++) 

    rabbitSortByWeight.pop();

原始列表怎么样?

顺便说一句,如果我有一个列表,那么我想把它放在priority_queue中,是否有比一个接一个地推送元素更好的方法?

3 个答案:

答案 0 :(得分:2)

为什么不简单地使用std::priority_queue的{​​{3}}方法来获取要弹出的元素的值并使用std :: list的top方法?

作为示例(假设队列存储指向列表元素的指针:

myList.remove(*(myQueue.top());

或(如果队列也存储引用):

myList.remove(myQueue.top());

答案 1 :(得分:1)

所以这就是为什么Arch的代码不是完全工作的原因,我认为将它显示给OP可能更好。缺少的链接是 equality operator ==(),用于从std :: list&lt;&gt;中删除。如果没有std::list<T>::remove(),就无法比较发送的对象是否是正在检查的对象。

#include <iostream>
#include <iterator>
#include <list>
#include <vector>
#include <queue>
#include <iomanip>
#include <ctime>
using namespace std;

// my rabbit (I don't have yours).
struct Rabbit
{
    Rabbit(int weight=0, int size=0)
       : weight(weight), size(size) {};

    int weight;
    int size;

    // needed for std::list<>::remove()
    bool operator ==(const Rabbit& other)
    {
        return weight == other.weight
            && size == other.size;
    }
};

// write to output stream
std::ostream& operator <<(std::ostream& os, const Rabbit& rabbit)
{
    os << '[' << setw(2) << rabbit.weight << ',' << setw(2) << rabbit.size << ']';
    return os;
}

// functor for comparing two rabbits by address
struct CompareRabbitPtrs
{
    bool operator ()(const Rabbit* left, const Rabbit* right)
    {
        return right->weight < left->weight ||
              (right->weight == left->weight && right->size < left->size);
    }
};

// some typedefs to make life a little easier. first the list
typedef std::list<Rabbit> RabbitList;

// now the priority_queue
typedef std::priority_queue<Rabbit*, std::vector<Rabbit*>, CompareRabbitPtrs> RabbitQueue;

int main()
{
    // seed RNG
    std::srand((unsigned)time(0));

    RabbitList rabbits;
    RabbitQueue rq;

    // load up your rabbits.
    for (int i=1;i<12;++i)
    {
        rabbits.push_back(Rabbit(std::rand() % 10 + 3,std::rand() % 20 + 5));
        rq.push(&rabbits.back());
    }

    // show rabbits
    std::copy(rabbits.begin(), rabbits.end(),
              ostream_iterator<Rabbit>(cout,"\n"));
    cout << endl;

    // remove top N rabbits, in this case 2
    for (int i=0;i<2;++i)
    {
        rabbits.remove(*rq.top());
        rq.pop();
    }

    // show rabbits again.
    std::copy(rabbits.begin(), rabbits.end(),
              ostream_iterator<Rabbit>(cout,"\n"));

    return 0;
}

示例运行输出

[11,17]
[ 6,17]
[ 8,11]
[12,14]
[ 7, 8]
[ 6,19]
[11,16]
[10,19]
[ 6,21]
[10,14]
[ 7,13]

[11,17]
[ 8,11]
[12,14]
[ 7, 8]
[11,16]
[10,19]
[ 6,21]
[10,14]
[ 7,13]

答案 2 :(得分:0)

我有两种方法可以解决这个问题。

该示例假定Rabbit类具有公共id成员。

1。我会将所有兔子存放在一个列表中,并将兔子分类到位。如果兔子已经按特定顺序列入清单 - 这可能是一个问题。

std::list<Rabbit> l;
for(int i=0; i<10; i++) 
    l.push_back(Rabbit(rand() % 10));   

auto comp = [](const Rabbit& a, const Rabbit& b) -> bool{ return a.id > b.id; };
l.sort<decltype(comp)>(comp);

int numToRemove = 3;
for(int i=0; i<numToRemove; i++) l.pop_back();

这将删除具有最低ID的3只兔子。

2。我会完全跳过列表,然后直接使用priority_queue。这样一来,当你把兔子弹出来时,一切都会被分类。请注意,priority_queue还有其他限制,可能不符合您的需要。

auto comp = [](Rabbit* a, Rabbit* b) { return a->id > b->id; };
std::priority_queue<Rabbit*, std::vector<Rabbit*>, decltype(comp)> q(comp);

for(int i=0; i<10; i++) 
    q.push_back(new Rabbit(rand() % 10));   

int numToRemove = 3;
for(int i=0; i<numToRemove; i++)
{
    delete q.top();;
    q.pop();
}