使用自定义值比较器提升Min-Queue

时间:2014-01-30 12:00:56

标签: c++ boost heap

我想在稀疏图上实现最短路径搜索(这不是一个提升图,可能无法有效地转换为一个),因此我自然而然地坚持使用优先级队列来实现Dijkstras算法。由于我的图形是自定义的,我需要将距离比较作为函数对象实现并将其交给队列:

#include <boost/heap/fibonacci_heap.hpp>
#include <iostream>
#include <climits>

#define BIG (INT_MAX / 2)

struct node_compare {
  std::vector<int> dist;

  void set(int node, int d) {
    dist[node] = d;
  }

  node_compare(int dim) : dist(dim, BIG) {};

  /* this is a 'greater than' because boost implements max-heaps */
  bool operator()(const int& n1, const int& n2) const { 
    std::cout << "Comparing " << n1 << " < " << n2 << " = " << dist[n1] << " > " << dist[n2] << std::endl;
    return dist[n1] > dist[n2];
  }

};

typedef boost::heap::fibonacci_heap<int,  boost::heap::compare<node_compare>> priority_queue;

int main(int argc, char** argv) {
  /* comparator implementation, based on distances */
  node_compare cmp(5);

  priority_queue pq(cmp);

  cmp.set(3, 10);

  for (int i = 0; i < 5; i++)
    pq.push(i);

  while(!pq.empty()) {
    std::cout << pq.top() << std::endl;
    pq.pop();
  }
}

令我印象深刻的是,优先级队列似乎构建了自己的node_compare实例,尽管我在构造函数中提供了一个实例。这甚至不可能,因为node_compare没有默认构造函数......

我知道这看起来有点像“请为我找到那个错误” - 问题,但我真的不知道我是否错过了一些重要的C ++语义或提升逻辑。

1 个答案:

答案 0 :(得分:1)

堆确实存储了它自己的node_compare实例,但是没有默认构造它,但是copy会从你在构造函数中传递的对象构造它。

因此,在行priority_queue pq(cmp);中,队列使用自动生成的cmp类的复制构造函数来复制node_compare对象。

如果在创建cmp.set(3, 10);之前调用priority_queue,则也应在队列的比较器中设置它。

我担心你在创建堆后无法更改比较器。堆对象具有value_comp()成员函数,该函数返回对比较器的const引用,因此您无法更改返回的比较器。我认为您无法更改比较器,因为这会使堆中的数据结构无效。

但是你可以存储比较器内距离向量的引用:

struct node_compare {
    const std::vector<int> &dist_;

    node_compare(const std::vector<int> &dist) : dist(dist) {};

    bool operator()(const int& n1, const int& n2) const { 
        return dist_[n1] > dist_[n2];
    }
};

您只需要小心,在向堆中添加元素后不要更改传递的距离向量。