Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/155.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何使用std::priority\u队列创建固定大小的最小堆?_C++_Algorithm - Fatal编程技术网

C++ 如何使用std::priority\u队列创建固定大小的最小堆?

C++ 如何使用std::priority\u队列创建固定大小的最小堆?,c++,algorithm,C++,Algorithm,我可以将最小堆定义为: priority_queue<int, vector<int>, greater> pq; 优先级队列pq; 我有一个整数流。最小堆的大小是一个固定值k。优先级队列似乎无法做到这一点。如果要使用std::priority\u队列,将队列的大小限制为k元素是很简单的。但是请注意,您需要使用最大堆,而不是最小堆,因为您需要知道是否应将新到达的值插入堆中,如果该值小于堆中当前的最大值,则会发生这种情况 class Topk { public:

我可以将最小堆定义为:

priority_queue<int, vector<int>, greater> pq;
优先级队列pq;

我有一个整数流。最小堆的大小是一个固定值k。优先级队列似乎无法做到这一点。

如果要使用
std::priority\u队列
,将队列的大小限制为
k
元素是很简单的。但是请注意,您需要使用最大堆,而不是最小堆,因为您需要知道是否应将新到达的值插入堆中,如果该值小于堆中当前的最大值,则会发生这种情况

class Topk {
  public:
    Topk(int k) : k_(k) {}
    void insert(int value) {
      if (q_.size() < k_) q_.push(value);
      else if (value < q_.top()) { q_.pop(); q_.push(value); }
    }
    std::vector<int> finalize() {
      std::vector<int> result(q_.size());
      while (q_.size()) {
        result[q_.size() - 1] = q_.top();
        q_.pop();
      }
      return result;
    }
  private:
    int k_;
    std::priority_queue<int> q_;
}
class-Topk{
公众:
Topk(intk):k_k(k){}
无效插入(int值){
如果(q_u.size()
仅使用堆算法实际上并不复杂:

class Topk {
  public:
    Topk(int k) : k_(k) {}
    void insert(int value) {
      if (c_.size() < k_) {
        c_.push_back(value);
        if (c_.size() == k_) make_heap(c_.begin(), c_.end());
      }
      else if (value < c_[0]) {
        /* See note below */
        pop_heap(c_.begin(), c_.end());
        c_.back() = value;
        push_heap(c_.begin(), c_.end());
      }
    }
    std::vector<int> finalize() {
      if (c_.size() < k_)
        std::sort(c_.begin(), c_.end());
      else
        sort_heap(c_.begin(), c_end());
      std::vector<int> c;
      std::swap(c, c_);
      return std::move(c);
    }
  private:
    /* invariant: if c_.size() == k, then c_ is a maxheap. */
    int k_;
    std::vector<int> c_;
}
class-Topk{
公众:
Topk(intk):k_k(k){}
无效插入(int值){
如果(c_u0.size()

注意:
不包括
堆筛选操作,这对于此应用程序来说是不幸的;pop/swap/push操作可以替换为swap/sift\U down。这仍然是O(logk),但可能会稍微快一些。

如果您有一个迭代器,并且不需要异步执行,那么可以使用
std::partial_sort

std::vector<int> x{10, 5, 1, 2, 3};
std::partial_sort(x.begin(), x.begin() + k, x.end());
std::向量x{10,5,1,2,3};
部分排序(x.begin(),x.begin()+k,x.end());

这给出了运行时复杂度大致为
O(nlogk)
的前k个元素。

您真的是指固定大小,还是指最大大小?如果大小确实是固定的,那么队列中的初始值是多少?基本上,它是大小为k的最小堆。其目的是找到一个数字流中的k个最小数,这根本不能回答rici提出的问题。您是从大小为
k
开始的,还是从空堆开始的,并且不希望元素的数量增长超过
k
?如果是前者,那么您在堆中放置的
k
整数是什么?“目的是找到数字流中的k个最小数。”为什么不对数据流进行排序并取前k个元素?@101010:因为这就是为什么您使用大小有界的堆。对整个数据集进行排序需要您立即将整个数据集拉入内存(或处理溢出到磁盘并重新读取),这是
O(n log n)
工作。使用有界大小的堆来做这项工作会将工作减少到
O(n log k)
,其中
n
是输入流的大小,
k
是有界堆的大小(可能小得多)。我认为对于使用优先级队列的实现,对于
的void insert(int value){if(q_u.size()
,'if(q_.size()@rici:
是。我的意思是当队列已满时(
'if(q.size()>k)
)。您通过使用最大堆实现了“最小堆”。我说的对吗?q.size不能大于k_。充其量是平等的。这是一个真正的最大堆;这里没有什么诡计。@Unni:我们的想法是重置
Topk
对象并返回向量,而不复制元素。交换将
c
重置为空向量,
move
使用移动语义而不是复制语义安排要返回的原始文件。