例如,我想从输入向量中选出第k个最大的元素。
我知道使用QuickSelect std :: nth_element可以做得更好。
我的问题是如何将std :: priority_queue的基础容器std :: vector复制到另一个向量,而不是解决这个编码问题。
priority_queue<int, vector<int>, greater<int>> pq;
for (int num : nums) {
pq.push(num);
if (pq.size() > k) {
pq.pop();
}
}
我的方式很愚蠢:
vector<int> res;
while (!pq.empty()) {
res.push_back(pq.top());
pq.pop();
}
有更好的方法吗?
我们可以像
那样做vector<int> res = pq;
不需要订购前k个元素。
答案 0 :(得分:2)
不,您无法在不弹出的情况下访问priority_queue的所有元素。还没有内置的方法来移动元素,但有一种方法,使用const cast。对于整数来说,这肯定是不值得的,但想象一下这种类型的复制成本很高。只要pq本身不在const存储中(即,以const开头声明的const),这个技巧就是安全的,这对于优先级队列来说应该是罕见的。
vector<int> res;
while (!pq.empty()) {
res.push_back(std::move(const_cast<int&>(pq.top())));
pq.pop();
}
答案 1 :(得分:2)
您可以在开头使用vector<int>
。
将此向量视为堆,包含std::make_heap
,std::push_heap
,std::pop_heap
。
这样,你可以复制矢量。
答案 2 :(得分:0)
c
的数据成员priority_queue
是protected
,这意味着只有派生类才能访问它。您可以这样编写extractable_priority_queue
:
template<class PQ>
class Extractable : public PQ {
public:
using PQ::PQ;
using typename PQ::container_type;
container_type&& container() && { return std::move(this->c); }
const container_type& container() const & { return this->c; }
container_type& container() & { return this->c; }
container_type sorted_container() && {
std::sort_heap(this->c.begin(), this->c.end(), this->comp);
return std::move(this->c);
}
};
然后:
Extractable<std::priority_queue<int, std::vector<int>, std::greater<int>>> pq;
for (int num : nums) {
pq.push(num);
if (pq.size() > k) {
pq.pop();
}
}
std::vector<int> res = std::move(pq).container();
如果您需要对前k个项目进行排序(您说不是的话),那么:
std::vector<int> res = std::move(pq).sorted_container();
写会更好
template<class T, class Container, class Comparator>
class ExtractablePriorityQueue :
public std::priority_queue<T, Container, Comparator> {
?对于某些用例,可能是相当不错的。就我而言,我仅针对实现它所需要做的打字量进行了优化。 :)