我有一个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中,是否有比一个接一个地推送元素更好的方法?
答案 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();
}