C ++ - 如何将元素从std :: priority_queue复制到std :: vector

时间:2016-11-20 20:55:17

标签: c++ c++11

例如,我想从输入向量中选出第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个元素。

3 个答案:

答案 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_heapstd::push_heapstd::pop_heap

这样,你可以复制矢量。

答案 2 :(得分:0)

c的数据成员priority_queueprotected,这意味着只有派生类才能访问它。您可以这样编写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> {

?对于某些用例,可能是相当不错的。就我而言,我仅针对实现它所需要做的打字量进行了优化。 :)