繁体   English   中英

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

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

为什么当priority_queue 用于单一数据类型时,比如'int',我们这样初始化它: priority_queue<int> ; 但是,当它用一对初始化时,我们添加第二个类型为向量priority_queue<pair<int,int>, vector<pair<int,int>>>的参数?

此外,我注意到添加指定排序的第三个参数的几种方法。

方法 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;

方法 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);

我的问题

  1. 为什么priority_queue的第二个参数是一个vector 这是什么意思,什么时候需要指定第二个参数?
  2. 在方法 2 中,为什么这个 lambda 需要decltype
  3. 方法2中,为什么leaderBoard需要用(myComp)初始化
  4. 在方法 2 中,为什么不能直接将我的 lambda 指定为第三个参数?
  5. A.second > B.secondA.second < B.second什么区别? 你怎么记得哪个是升序,哪个是降序?

为什么当priority_queue与单一数据类型一起使用时,比如'int',我们这样初始化它: priority_queue<int> [...]?

因为std::priority_queue是一个 class 模板,定义如下:

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

如您所见,您可以仅提供T实例化此 class ,因为类型的 rest 将被默认。 您可以在此处阅读有关模板默认 arguments 的更多信息。

但是,当它用一对初始化时,我们添加第二个类型为向量priority_queue<pair<int,int>, vector<pair<int,int>>>的参数?

因为有人想要明确。 priority_queue<pair<int, int>>等价于priority_queue<pair<int,int>, vector<pair<int,int>>> ,因为第二个模板类型( vector<pair<int, int>> )将是默认存在。

  1. 为什么priority_queue的第二个参数是向量? 这是什么意思,什么时候需要指定第二个参数?

我们不需要明确指定它。 第二个模板参数是用于数据内部表示的类型。 std::priority_queue是一个容器适配器,这意味着它本身不是一个容器 - 它使用一些其他容器并用某种实用程序包装它。

  1. 在方法 2 中,为什么这个 lambda 需要 decltype?

因为你需要提供一个type myCompare是一个struct ,所以它是一个类型的名称。 myComp不是一个类型,它是一个变量。 你想得到它声明的类型吗? 使用decltype

  1. 在方法 2 中,为什么需要使用(myComp)初始化 object 排行榜?

因为你不能默认构造一个 object 给定decltype的 lambda ( 这在 C++20 中得到了放松)。 您需要使用以下构造函数:

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

它期望将用作比较器的可调用对象(在本例中为 lambda)。

  1. 在方法 2 中,为什么不能直接将我的 lambda 指定为第三个参数?

你的意思是作为第三个template参数? 因为到目前为止,lambdas 不能在未评估的上下文中使用,而为模板提供类型就是其中之一。

5.1。 A.second > B.secondA.second < B.second什么区别?

差别相当明显。 一个检查A.second是否大于第二个参数,另一个检查是否相反。 它通常用于排序(用于比较元素)。

5.2 你怎么记得哪个是升序,哪个是降序?

这很容易 - C++的概念是在左侧参数和右侧参数之间使用< ,如下所示: left_hand_side < right_hand_side

为什么priority_queue的第二个参数是向量?

您可以使用任何满足某些要求的容器。 vector是一个合理的默认选择。

这是什么意思,什么时候需要指定第二个参数?

如果要更改其默认值,或者要指定第三个。 std::priority_queue<std::pair<int,int>>是没有指定第二个参数的有效类型。

在方法 2 中,为什么这个 lambda 需要 decltype?

如果要使用自定义比较器,则必须将其类型指定为第三个模板参数。 每个 lambda 都有自己独特的类型,获得它的唯一方法是通过decltype

方法2中,为什么object排行榜需要用(myComp)初始化

因为可以默认构造基于struct的比较器,但基于 lambda 的比较器不能。 相关的构造函数是

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

如果您不提供compare ,则使用Compare() myCompare()是一个有效值,而decltype(myComp)()不是。

在方法 2 中,为什么不能直接将我的 lambda 指定为第三个参数?

您需要一个类型,而不是该类型的值。

A.second > B.second 和 A.second < B.second 有什么区别?

交换 arguments 的顺序(或等价的<> )将最小堆转换为最大堆,反之亦然,即该顺序确定.top()将返回哪个元素,最小或最大。

方法2中,为什么object排行榜需要用(myComp)初始化

这取决于您使用的 C++ 标准。 在 C++20 之前,您需要将由 lambda 表达式创建的仿函数传递给priority_queue构造函数,因为在 C++20 之前的 lambdas 不是默认可构造的。

从 C++20 开始,您可以编写:

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

它会正常工作,因为编译器知道 lambda 的类型 - 由decltype(myComp)指定,并且它可以调用其默认 ctor。


在方法 2 中,为什么不能直接将我的 lambda 指定为第三个参数?

是的,你可以,但你仍然需要使用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