Почему Vector используется в качестве второго аргумента очереди приоритетов? - PullRequest
0 голосов
/ 06 ноября 2019

Почему при использовании priority_queue с одним типом данных, таким как 'int', мы инициализируем его следующим образом: priority_queue<int>;но когда он инициализируется парой, мы добавляем второй параметр типа vector 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 - Лямбда

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 a vector? Что это значит и когда нужно указывать этот второй параметр?
  2. В методе 2, почему decltype требуется для этой лямбды?
  3. В методе 2, почему объект leaderBoard нужно инициализировать с помощью (myComp)
  4. В методе 2, почему я не могу указать свою лямбду в качестве третьего аргумента напрямую?
  5. В чем разница между A.second > B.second и A.second < B.second? Как вы помните, что означает восходящий порядок, а какой - нисходящий?

Ответы [ 3 ]

2 голосов
/ 06 ноября 2019

Почему, когда priority_queue используется с одним типом данных, таким как 'int', мы инициализируем его следующим образом: priority_queue<int> [...]?

Поскольку std::priority_queue является шаблоном класса, определенным следующим образом:

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

Как видите, вы можете создать экземпляр этого класса, предоставив только T, потому что остальные типы будут по умолчанию. Подробнее о шаблонных аргументах по умолчанию вы можете прочитать здесь .

, но когда он инициализируется парой, мы добавляем второй параметр типа vector 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 - это контейнерный адаптер , что означает, что он сам по себе не является контейнером - он использует какой-то другой контейнер и оборачивает его определенными утилитами.

В методе 2, зачем нужен decltype с этой лямбдой?

Поскольку вам нужно предоставить type . myCompare - это struct, поэтому это имя типа. myComp это не тип, это переменная. Вы хотите получить объявленный тип ? Используйте decltype.

В методе 2, почему объект leaderBoard нужно инициализировать с помощью (myComp)?

Поскольку вы не можете создать объект по умолчанию с учетом decltype лямбды. Вам необходимо использовать следующий конструктор:

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

, который ожидает вызываемый объект (в данном случае - лямбду), который будет использоваться в качестве компаратора.

В методе 2, почему я не могу указать свою лямбду в качестве третьего аргумента напрямую?

Вы имеете в виду в качестве аргумента thirs template? Потому что на данный момент лямбды нельзя использовать в неоцененных контекстах, и одним из них является предоставление типа для шаблона.

5.1. В чем разница между A.second > B.second и A.second < B.second?

Разница очевидна. Один проверяет, является ли A.second большим, чем второй аргумент, а другой - обратным.

5.2 Как вы помните, какой из них означает восходящий, а какой - нисходящий?

Это довольно просто - концепция C++ заключается в использовании < между левой стороны стороны аргументом и справа сторона стороны аргумент, вот так: left_hand_side < right_hand_side.

1 голос
/ 06 ноября 2019

В методе 2, почему объект leaderBoard нужно инициализировать с помощью (myComp)

, это зависит от того, какой стандарт C ++ вы используете. До C ++ 20 вам нужно было передать функтор, созданный лямбда-выражением, в конструктор priority_queue, потому что лямбды до C ++ 20 не были конструируемыми по умолчанию.

Начиная с C ++ 20 вы можете написать:

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

, он будет работать нормально, потому что компилятор знает тип лямбда-выражения, заданного decltype(myComp), и может вызывать его ctor по умолчанию.


В методе 2, почему я не могу указать свою лямбду в качестве третьего аргумента напрямую?

Да, вы можете, но вам все равно нужно использовать 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;
1 голос
/ 06 ноября 2019

Почему второй параметр priority_queue является вектором?

Вы можете использовать любой контейнер, который удовлетворяет определенным требованиям . vector - разумный выбор по умолчанию.

Что это значит и когда нужно указывать этот второй параметр?

Если вы хотите изменить его по умолчаниюзначение, или вы хотите указать третий. std::priority_queue<std::pair<int,int>> является допустимым типом без указания второго параметра.

В методе 2, почему требуется decltype с этой лямбдой?

Если вы хотите использовать пользовательскийкомпаратор, вы должны указать его тип в качестве третьего параметра шаблона. Каждая лямбда имеет свой собственный уникальный тип, единственный способ получить его - через decltype.

В методе 2, почему объект leaderBoard нужно инициализировать с помощью (myComp)

Потому что компаратор на основе struct может быть создан по умолчанию, а лямбда - нет. Соответствующие конструкторы:

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

Если вы не предоставите compare, используется Compare(). myCompare() является допустимым значением, а decltype(myComp)() - нет.

В методе 2, почему я не могу указать свою лямбду в качестве третьего аргумента напрямую?

Вам нужен тип, а не значение этого типа.

В чем разница между A.second> B.second и A.second

Смена порядка аргументов (или, что эквивалентно, < и >) превращает минимальную кучу в максимальную кучу и наоборот, т.е. этот порядок определяет, какой элемент будет возвращенна .top(), самый маленький или самый большой.

...