简体   繁体   English

优先级队列如何在内部工作?

[英]c++ - Priority Queue - How does it work internally?

Say I have this declaration of a priority queue: 假设我有以下优先级队列声明:

    struct orderByRewards{

    bool operator() (pair<int,pair<int,int> > a, pair<int, pair<int, int> > b){
        return a.first < b.first;
    }
};

priority_queue<pair<int,pair<int,int> >, vector<pair<int,pair<int,int> > >, orderByRewards> Q;

I was wondering if anybody could take their time and explain me how does the compiler interpret the compare class. 我想知道是否有人可以花时间解释我的编译器如何解释比较类。

  • Why do I need to overload the () operator ? 为什么需要重载()运算符?
  • Also, where's the () operator used in its comparing process ? 另外,在比较过程中使用()运算符在哪里?

It feels a little weird, especially since I am not really comfortable with templates and all OOP concepts. 感觉有点奇怪,尤其是因为我对模板和所有OOP概念都不是很满意。

Why do we need to declare the type of a single object and the container type ? 为什么我们需要声明单个对象的类型和容器类型?

You are not required to overfload the operator(). 您不需要使operator()重载。 You can declare your custom method: 您可以声明自定义方法:

typedef bool (*comp)(int,int);
bool compare(int a, int b)
{
   return (a<b);
}
int main()
{
    std::priority_queue<int,std::vector<int>, comp> pq(compare);
    return 0;
}

Updated : As @WhozCraig pointed out: It is possible to use this object without overloading the operator() but the compiler will face an easier situation inlining operator() comparison function rather than runtime-provided dereferenced comparison function 更新 :正如@WhozCraig指出的:可以在不重载operator()的情况下使用此对象,但是编译器将面临内联operator()比较函数而不是运行时提供的解引用比较函数的更简单情况。

You're essentially asking about function objects (or functors). 您实际上是在询问函数对象(或函子)。 A function object is one that overloads operator() . 函数对象是一个重载operator() You can use such an object as though it were a function. 您可以将其当作函数来使用。 The standard provides a few comparison functors (like your orderByRewards ). 该标准提供了一些比较函子(例如您的orderByRewards )。 For example, std::less looks something like this: 例如, std::less看起来像这样:

template <class T>
struct less {
  constexpr bool operator()(const T &lhs, const T &rhs) const 
  {
    return lhs < rhs;
  }
};

As we can see, the overloaded operator() just compares the two arguments using < and then returns the boolean result. 如我们所见,重载的operator()仅使用<比较两个参数,然后返回布尔结果。 To use this, you need to create an object of type std::less and then use the function call syntax on it: 要使用它,您需要创建一个std::less类型的对象,然后在其上使用函数调用语法:

std::less<int> compare;
assert(compare(5, 7) == true);

Even though compare is an object, we were able to use it like a function in compare(5, 7) . 即使compare是一个对象,我们也可以像compare(5, 7)的函数一样使用它。

So now we know that your type orderByRewards is a function object type. 现在我们知道您的类型orderByRewards是函数对象类型。 You are passing it as a template type argument of std::priority_queue . 您将其作为std::priority_queue的模板类型参数传递。 The implementation of std::priority_queue can then create objects of this comparison function object when it needs to compare elements within the queue. 然后,当需要比较队列中的元素时, std::priority_queue的实现可以创建此比较函数对象的对象。

Consider a simpler example: 考虑一个更简单的示例:

template <typename T, typename Comp>
struct foo {
  void bar(T a, T b) {
    Comp compare;
    if (compare(a, b)) {
      std::cout << "True" << std::endl;
    } else {
      std::cout << "False" << std::endl;
    }
  }
};

It's a silly example, but it gets the point across. 这是一个愚蠢的例子,但可以理解这一点。 We can use this like so: 我们可以这样使用:

foo<int, std::less<int>> my_foo;
my_foo.bar(5, 7); // Will print true

We were able to configure foo , by passing it some arbitrary comparison functor type, that its member function bar was able to instantiate and use. 我们可以通过传递foo任意比较函子类型来配置foo ,使其成员函数bar可以实例化和使用。

So in the same way, you are configuration std::priority_queue by giving it a comparison functor type that it can use to order elements within the queue. 因此,以同样的方式,通过为std::priority_queue提供一个比较函子类型来配置std::priority_queue ,它可用于对队列中的元素进行排序。 This is how it determines priority between elements. 这就是它确定元素之间优先级的方式。 In fact, the default template type argument for std::priority_queue is std::less . 实际上, std::priority_queue的默认模板类型参数是std::less

Perhaps it would make the most sense to look at the definition of std::priority_queue and work from there. 查看std::priority_queue的定义并从那里开始工作可能是最有意义的。

template <class T, class Container = vector<T>, 
          class Compare = less<typename Container::value_type> >
class priority_queue {

This says that Compare is some type, and defaults to std::less<T> , for T = the value_type of the underlying container. 这表示Compare是某种类型,默认为std::less<T> ,因为T =基础容器的value_type。 This compensates for the possibility that you might do something slightly insane like creating a priority_queue of one type, but have the underlying container hold another type (though that's not particularly likely, except by accident). 这弥补了您可能会有些疯狂的事情(例如创建一种类型的priority_queue)但使基础容器容纳另一种类型的可能性的可能性(尽管并非偶然,但这种可能性不大)。

std::less , in turn, is defined like this: std::less依次定义如下:

template <class T> struct less {
    bool operator()(const T& x, const T& y) const;
    // plus a few typedefs for the argument and return types.
};

In short, it's a type defined with only one publicly available operation: an operator() that can be passed two items that it compares, and returns a bool to indicate whether the first is less than the second. 简而言之,它是一种仅由一个公开可用的操作定义的类型: operator() ,可以传递要比较的两个项目,并返回bool以指示第一个是否小于第二个。

Since that's what std::priority_queue expects to use, whatever you provide must support essentially the same function call-like syntax and semantics (eg, the operator() should take const arguments and should itself be const-qualified). 因为那是什么std::priority_queue希望使用,无论您必须提供基本支持相同的函数调用的语法和语义(例如, operator()应采取const参数和本身应该是const修饰)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM