我使用STL priority_queue来收集我自己的类Lettura的对象。
//---------LETTURA----------
enum Priority {zero, standard, urgent};
class Lettura{
public:
int valore;
char sensore;
Priority priorita;
Lettura(): valore(0),sensore('\0'),priorita(zero){}
Lettura(const int val, const char s='\0', const Priority p=zero): valore(val),sensore(s), priorita(p){}
friend ostream& operator<<(ostream& out, const Lettura & lett);
};
我希望它们按照渐弱的顺序弹出&#34; priorita&#34;,但我也希望在普通队列中使用FIFO策略弹出相同优先级的元素。 我以随机顺序获得相同优先级的元素:
top: l5 urgent
top: l1 standard
top: l4 standard
top: l6 standard
top: l2 standard
top: l3 standard
我希望FIFO顺序中具有相同优先级的元素:
top: l5 urgent
top: l1 standard
top: l2 standard
top: l3 standard
top: l4 standard
top: l6 standard
这是我的代码:
int main() {
std::priority_queue<Lettura, std::vector<Lettura>, std::less<Lettura> > coda;
Lettura l1(50,'a',standard);
Lettura l2(50,'b',standard);
Lettura l3(120,'c',standard);
Lettura l4(100,'d',standard);
Lettura l5(30,'e',urgent);
Lettura l6(35,'f',standard);
coda.push(l1);
coda.push(l2);
coda.push(l3);
coda.push(l4);
coda.push(l5);
coda.push(l6);
cout<<"top: "<<coda.top()<<"\n"; coda.pop();
cout<<"top: "<<coda.top()<<"\n"; coda.pop();
cout<<"top: "<<coda.top()<<"\n"; coda.pop();
cout<<"top: "<<coda.top()<<"\n"; coda.pop();
cout<<"top: "<<coda.top()<<"\n"; coda.pop();
cout<<"top: "<<coda.top()<<"\n"; coda.pop();
}
我已经实施了这些比较方法:
bool operator<(const Lettura& l1, const Lettura& l2){
return l1.priorita < l2.priorita;
}
bool operator<=(const Lettura& l1, const Lettura& l2){
return l1.priorita <= l2.priorita;
}
我也试过不同的队列构造函数,但没有成功:
std::priority_queue<Lettura> coda;
std::priority_queue<Lettura, std::vector<Lettura>, std::less_equal<Lettura> > coda;
有人能帮助我吗?
答案 0 :(得分:6)
您的代码似乎正常工作,因为您首先获得紧急项目。在基于堆的优先级队列中,插入时间没有子排序,因此您将以未定义的顺序获取具有相同优先级的项目,除了它们将位于具有更高优先级的项目之后。您需要添加一个额外的字段,例如放入队列的时间,并在比较运算符中将其与Priority枚举一起使用。
答案 1 :(得分:1)
这是另一个可能的stable_priority_queue实现,它保留了priority_queue提供的相同接口:
template <class T>
struct stable_element
{
stable_element(T&& o, std::size_t c)
: object_(std::move(o))
, insertion_order_(c)
{
}
stable_element(const T& o, std::size_t c)
: object_(o)
, insertion_order_(c)
{
}
operator T() { return object_; }
T object_;
std::size_t insertion_order_;
};
template <class T>
bool operator<(const stable_element<T>& lhs, const stable_element<T>& rhs)
{
return (lhs.object_ < rhs.object_) || (!(rhs.object_ < lhs.object_) && (rhs.insertion_order_ < lhs.insertion_order_));
}
template <class T,
class Container = std::vector<stable_element<T>>,
class Compare = std::less<typename Container::value_type>>
class stable_priority_queue : public std::priority_queue<stable_element<T>, Container, Compare>
{
using stableT = stable_element<T>;
using std::priority_queue<stableT, Container, Compare>::priority_queue;
public:
const T& top() { return this->c.front().object_; }
void push(const T& value) {
this->c.push_back(stableT(value, counter_++));
std::push_heap(this->c.begin(), this->c.end(), this->comp);
}
void push(T&& value) {
this->c.push_back(stableT(std::move(value), counter_++));
std::push_heap(this->c.begin(), this->c.end(), this->comp);
}
template<class ... Args>
void emplace(Args&&... args) {
this->c.emplace_back(T(std::forward<Args>(args)...), counter_++);
std::push_heap(this->c.begin(), this->c.end(), this->comp);
}
void pop() {
std::pop_heap(this->c.begin(), this->c.end(), this->comp);
this->c.pop_back();
if (this->empty()) counter_ = 0;
}
protected:
std::size_t counter_ = 0;
};
在std :: priority_queue中,受保护的成员c
和comp
分别对应于底层容器和比较功能对象。使用这种从std :: priority_queue继承的方法,我们需要修改top
,push
,emplace
和pop
的行为。 std::priority_queue的每个功能的文档都根据c
和comp
成员的功能提供了这些功能的实现。这对于用stable_element<T>
重写修改后的成员函数非常有帮助。
要将此stable_priority_queue用于OP用例,我们只需要提供bool operator<(const Lettura& l, const Lettura& r) { return l.priorita < r.priorita; }
来根据需要对优先级进行排序:
enum Priority
{
zero, standard, urgent
};
inline std::ostream& operator <<(std::ostream& os, const Priority& p)
{
switch (p) {
case zero:
os << "zero"; break;
case standard:
os << "standard"; break;
case urgent:
os << "urgent"; break;
}
return os;
}
class Lettura
{
public:
int valore;
char sensore;
Priority priorita;
Lettura()
: valore(0)
, sensore('\0')
, priorita(zero) {}
Lettura(const int val, const char s = '\0', const Priority p = zero)
: valore(val)
, sensore(s)
, priorita(p) {}
friend std::ostream& operator <<(std::ostream& out, const Lettura& lett)
{
return out << "{ valore: " << lett.valore << ", sensore: " << lett.sensore << ", priorita: " << lett.priorita
<< " }";
}
};
bool operator<(const Lettura& l, const Lettura& r)
{
return l.priorita < r.priorita;
}
int main()
{
stable_priority_queue<Lettura> coda;
Lettura l1(50, 'a', standard);
Lettura l2(50, 'b', standard);
Lettura l3(120, 'c', standard);
Lettura l5(30, 'e', urgent);
Lettura l6(35, 'f', standard);
coda.push(l1);
coda.push(l2);
coda.push(l3);
coda.emplace(100, 'd', standard);
coda.emplace(l5);
coda.emplace(l6);
while (!coda.empty()) {
std::cout << "top: " << coda.top() << "\n";
coda.pop();
}
}
输出:
top: { valore: 30, sensore: e, priorita: urgent }
top: { valore: 50, sensore: a, priorita: standard }
top: { valore: 50, sensore: b, priorita: standard }
top: { valore: 120, sensore: c, priorita: standard }
top: { valore: 100, sensore: d, priorita: standard }
top: { valore: 35, sensore: f, priorita: standard }
以下是LIVE所有这些放在一起的演示
答案 2 :(得分:0)
这是一个稳定优先级队列的简单实现。
当队列为空时,它会尝试通过将插入计数器归零来抵制排序耗尽:
#include <iostream>
#include <string>
#include <queue>
#include <algorithm>
enum Priority
{
zero, standard, urgent
};
inline std::ostream& operator <<(std::ostream& os, const Priority& p)
{
switch (p) {
case zero:
return os << "zero";
case standard:
return os << "standard";
case urgent:
return os << "urgent";
}
}
class Lettura
{
public:
int valore;
char sensore;
Priority priorita;
Lettura()
: valore(0)
, sensore('\0')
, priorita(zero) {}
Lettura(const int val, const char s = '\0', const Priority p = zero)
: valore(val)
, sensore(s)
, priorita(p) {}
friend std::ostream& operator <<(std::ostream& out, const Lettura& lett)
{
return out << "{ valore: " << lett.valore << ", sensore: " << lett.sensore << ", priorita: " << lett.priorita
<< " }";
}
};
template<class T, class Comp>
struct stable_priority_queue
{
using counter_type = std::size_t;
struct Proxy
{
Proxy(T&& o, counter_type c)
: object(std::move(o))
, insertion_order_(c) {}
Proxy(const T& o, counter_type c)
: object(o)
, insertion_order_(c) {}
T object;
counter_type insertion_order_;
};
struct ProxyComp
{
bool operator ()(Proxy const& l, Proxy const& r) const
{
if (major_order_(l.object, r.object))
return true;
if (major_order_(r.object, l.object))
return false;
return minor_order_(l.insertion_order_, r.insertion_order_);
}
Comp major_order_;
std::greater<> minor_order_;
};
decltype(auto) push(T item)
{
return queue_.emplace(std::move(item), counter_++);
}
T const& top() const
{
return queue_.top().object;
}
void pop()
{
queue_.pop();
if (queue_.empty())
counter_ = 0;
}
std::priority_queue<Proxy, std::vector<Proxy>, ProxyComp> queue_;
counter_type counter_ = 0;
};
struct lower_priority
{
bool operator ()(const Lettura& l, const Lettura& r) const
{
return l.priorita < r.priorita;
}
};
int main()
{
stable_priority_queue<Lettura, lower_priority> coda;
Lettura l1(50, 'a', standard);
Lettura l2(50, 'b', standard);
Lettura l3(120, 'c', standard);
Lettura l4(100, 'd', standard);
Lettura l5(30, 'e', urgent);
Lettura l6(35, 'f', standard);
coda.push(l1);
coda.push(l2);
coda.push(l3);
coda.push(l4);
coda.push(l5);
coda.push(l6);
std::cout << "top: " << coda.top() << "\n";
coda.pop();
std::cout << "top: " << coda.top() << "\n";
coda.pop();
std::cout << "top: " << coda.top() << "\n";
coda.pop();
std::cout << "top: " << coda.top() << "\n";
coda.pop();
std::cout << "top: " << coda.top() << "\n";
coda.pop();
std::cout << "top: " << coda.top() << "\n";
coda.pop();
}
预期结果:
top: { valore: 30, sensore: e, priorita: urgent }
top: { valore: 50, sensore: a, priorita: standard }
top: { valore: 50, sensore: b, priorita: standard }
top: { valore: 120, sensore: c, priorita: standard }
top: { valore: 100, sensore: d, priorita: standard }
top: { valore: 35, sensore: f, priorita: standard }
答案 3 :(得分:-4)
这似乎是编译器库和C ++标准的错误。它们破坏了在priority_queue中选择最大元素的算法。看看我根据堆打开的线程。
Why does std::is_heap use random access iterators instead of forward iterators?
我准备相应的提案。