简体   繁体   English

为什么向量被用作优先队列的第二个参数?

[英]Why is Vector used as a second argument to Priority Queue?

Why is it that when priority_queue is used with a single data type, like 'int', we initialise it like this: priority_queue<int> ;为什么当priority_queue 用于单一数据类型时,比如'int',我们这样初始化它: priority_queue<int> ; but, when it's initialized with a pair we add a second parameter of type vector priority_queue<pair<int,int>, vector<pair<int,int>>> ?但是,当它用一对初始化时,我们添加第二个类型为向量priority_queue<pair<int,int>, vector<pair<int,int>>>的参数?

Also, I've noticed several ways to add a third argument that specifies ordering.此外,我注意到添加指定排序的第三个参数的几种方法。

Method 1 - Struct方法 1 - 结构

struct myCompare {
   bool operator()(const pair<int, int>& A, const pair<int, int>& B) {
       return A.second < B.second;
   }
};

priority_queue<pair<int, int>, vector<pair<int, int>>, myCompare> leaderBoard;

Method 2 - Lambda方法 2 - Lambda

auto myComp = [](const pair<int, int>& A, const pair<int, int>& B) 
              {return A.second < B.second;};

priority_queue<pair<int, int>, vector<pair<int, int>>, decltype(myComp)> leaderBoard(myComp);

My Questions我的问题

  1. Why is the second parameter of priority_queue a vector ?为什么priority_queue的第二个参数是一个vector What does this mean and when does this second parameter need to be specified?这是什么意思,什么时候需要指定第二个参数?
  2. In method 2, why is decltype needed with this lambda?在方法 2 中,为什么这个 lambda 需要decltype
  3. In method 2, why does the object leaderBoard need to be initialised with (myComp)方法2中,为什么leaderBoard需要用(myComp)初始化
  4. In method 2, why can I not specify my lambda as the third argument directly?在方法 2 中,为什么不能直接将我的 lambda 指定为第三个参数?
  5. What is the difference between A.second > B.second and A.second < B.second ? A.second > B.secondA.second < B.second什么区别? How do you remember which one means ascending order, and which one is descending order?你怎么记得哪个是升序,哪个是降序?

Why is it that when priority_queue is used with a single data type, like 'int', we initialise it like this: priority_queue<int> [...]?为什么当priority_queue与单一数据类型一起使用时,比如'int',我们这样初始化它: priority_queue<int> [...]?

Because std::priority_queue is a class template defined as follows:因为std::priority_queue是一个 class 模板,定义如下:

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

As you can see, you can instantiate this class only providing the T , because the rest of the types will be defaulted.如您所见,您可以仅提供T实例化此 class ,因为类型的 rest 将被默认。 You can read more about template default arguments here .您可以在此处阅读有关模板默认 arguments 的更多信息。

but, when it's initialized with a pair we add a second parameter of type vector priority_queue<pair<int,int>, vector<pair<int,int>>> ?但是,当它用一对初始化时,我们添加第二个类型为向量priority_queue<pair<int,int>, vector<pair<int,int>>>的参数?

Because someone wanted to be explicit.因为有人想要明确。 priority_queue<pair<int, int>> is equivalent to priority_queue<pair<int,int>, vector<pair<int,int>>> , because the second template type ( vector<pair<int, int>> ) will be present by default. priority_queue<pair<int, int>>等价于priority_queue<pair<int,int>, vector<pair<int,int>>> ,因为第二个模板类型( vector<pair<int, int>> )将是默认存在。

  1. Why is the second parameter of priority_queue a vector?为什么priority_queue的第二个参数是向量? What does this mean and when does this second parameter need to be specified?这是什么意思,什么时候需要指定第二个参数?

We don't need to specify it explicitly .我们不需要明确指定它。 The second template parameter is a type use for internal representation of data.第二个模板参数是用于数据内部表示的类型。 std::priority_queue is a container adaptor , which means that it's not a container by itself - it uses some other container and wraps it with certain kind of utilities. std::priority_queue是一个容器适配器,这意味着它本身不是一个容器 - 它使用一些其他容器并用某种实用程序包装它。

  1. In method 2, why is decltype needed with this lambda?在方法 2 中,为什么这个 lambda 需要 decltype?

Because you need to provide a type .因为你需要提供一个type myCompare is a struct , so it's a name of a type. myCompare是一个struct ,所以它是一个类型的名称。 myComp is not a type, it's a variable. myComp不是一个类型,它是一个变量。 You wish to get its declared type ?你想得到它声明的类型吗? Use decltype .使用decltype

  1. In method 2, why does the object leaderBoard need to be initialised with (myComp) ?在方法 2 中,为什么需要使用(myComp)初始化 object 排行榜?

Because you cannot default construct an object given a decltype of a lambda ( this got relaxed in C++20 ).因为你不能默认构造一个 object 给定decltype的 lambda ( 这在 C++20 中得到了放松)。 You need to use the following constructor:您需要使用以下构造函数:

explicit priority_queue(const Compare& compare)
    : priority_queue(compare, Container()) { }

which expects a callable (in this case - the lambda) that will be used as a comparator.它期望将用作比较器的可调用对象(在本例中为 lambda)。

  1. In method 2, why can I not specify my lambda as the third argument directly?在方法 2 中,为什么不能直接将我的 lambda 指定为第三个参数?

You mean as the third template argument?你的意思是作为第三个template参数? Because as of right now, lambdas cannot be used in unevaluated contexts, and providing a type for a template is one of those.因为到目前为止,lambdas 不能在未评估的上下文中使用,而为模板提供类型就是其中之一。

5.1. 5.1。 What is the difference between A.second > B.second and A.second < B.second ? A.second > B.secondA.second < B.second什么区别?

The difference is quite blatant.差别相当明显。 One checks for A.second being greater than the second argument and the other one is the reverse.一个检查A.second是否大于第二个参数,另一个检查是否相反。 It is commonly used for sorting (for comparing elements).它通常用于排序(用于比较元素)。

5.2 How do you remember which one means ascending order, and which one is descending order? 5.2 你怎么记得哪个是升序,哪个是降序?

It's pretty easy - the C++ conception is to use < between the left hand side argument and the right hand side argument, like so: left_hand_side < right_hand_side .这很容易 - C++的概念是在左侧参数和右侧参数之间使用< ,如下所示: left_hand_side < right_hand_side

Why is the second parameter of priority_queue a vector?为什么priority_queue的第二个参数是向量?

You can use any container that satisfies certain requirements .您可以使用任何满足某些要求的容器。 vector is a reasonable default choice. vector是一个合理的默认选择。

What does this mean and when does this second parameter need to be specified?这是什么意思,什么时候需要指定第二个参数?

If either you want to change its default value, or you want to specify the third one.如果要更改其默认值,或者要指定第三个。 std::priority_queue<std::pair<int,int>> is a valid type without specifying the second paramater. std::priority_queue<std::pair<int,int>>是没有指定第二个参数的有效类型。

In method 2, why is decltype needed with this lambda?在方法 2 中,为什么这个 lambda 需要 decltype?

If you want to use a custom comparator, you have to specify its type as a third template parameter.如果要使用自定义比较器,则必须将其类型指定为第三个模板参数。 Each lambda has its own unique type, the only way to obtain it, is through decltype .每个 lambda 都有自己独特的类型,获得它的唯一方法是通过decltype

In method 2, why does the object leaderBoard need to be initialised with (myComp)方法2中,为什么object排行榜需要用(myComp)初始化

Because struct -based comparator can be default constructed, but lambda-based one can't.因为可以默认构造基于struct的比较器,但基于 lambda 的比较器不能。 The relevant constructors are相关的构造函数是

priority_queue() : priority_queue(Compare(), Container()) { }
priority_queue(const Compare& compare) : priority_queue(compare, Container()) { }

If you don't provide compare , Compare() is used.如果您不提供compare ,则使用Compare() myCompare() is a valid value, and decltype(myComp)() is not. myCompare()是一个有效值,而decltype(myComp)()不是。

In method 2, why can I not specify my lambda as the third argument directly?在方法 2 中,为什么不能直接将我的 lambda 指定为第三个参数?

You need a type, not a value of that type.您需要一个类型,而不是该类型的值。

What is the difference between A.second > B.second and A.second < B.second? A.second > B.second 和 A.second < B.second 有什么区别?

Swapping the order of arguments (or, equivalently, < and > ) turns a min-heap into a max-heap and vice versa, ie that order determines which element will be returned by .top() , the smallest or the largest.交换 arguments 的顺序(或等价的<> )将最小堆转换为最大堆,反之亦然,即该顺序确定.top()将返回哪个元素,最小或最大。

In method 2, why does the object leaderBoard need to be initialised with (myComp)方法2中,为什么object排行榜需要用(myComp)初始化

it depends on what C++ standard you use.这取决于您使用的 C++ 标准。 Before C++20 you need to pass functor created by lambda expression to priority_queue constructor because lambdas until C++20 were not default constructible.在 C++20 之前,您需要将由 lambda 表达式创建的仿函数传递给priority_queue构造函数,因为在 C++20 之前的 lambdas 不是默认可构造的。

Since C++20 you can write:从 C++20 开始,您可以编写:

priority_queue<pair<int, int>, vector<pair<int, int>>, decltype(myComp)> leaderBoard;

it will work fine because compiler knows type of lambda - specified by decltype(myComp) , and it can call its default ctor.它会正常工作,因为编译器知道 lambda 的类型 - 由decltype(myComp)指定,并且它可以调用其默认 ctor。


In method 2, why can I not specify my lambda as the third argument directly?在方法 2 中,为什么不能直接将我的 lambda 指定为第三个参数?

Yes, you can but you need to still use decltype to get comparator type:是的,你可以,但你仍然需要使用decltype来获取比较器类型:

priority_queue<pair<int, int>, vector<pair<int, int>>, 
     decltype( [](const pair<int, int>& A, const pair<int, int>& B) 
              {return A.second < B.second;} ) > leaderBoard;

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

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