Сортировка вектора пар

У меня есть вопрос о сортировке вектора пар:

std::vector<std::pair<double,Processor*>> baryProc;

этот вектор уже заполнен парами. Теперь я хотел отсортировать пары внутри вектора на основе двойного значения внутри пары.

ПРИМЕР:

предположим, у меня есть 3 пары внутри вектора. Пара 1 находится впереди, а пара 3 — в конце. Пара2 находится посередине:

pair1(1, proc1) 
pair2(3, proc2)
pair3(2.5, proc3)

теперь я хочу отсортировать пары на основе двойного значения. Так что порядок внутри вектора:

pair1(1, proc1) 
pair3(2.5, proc3)
pair2(3, proc2)

Как я мог это сделать? Я совсем застрял.


person user2633791    schedule 07.08.2013    source источник


Ответы (2)


В C++ у вас могут быть пользовательские функции сравнения, которые определяют, как решить, идет ли один элемент перед другим при сортировке. В вашем случае, учитывая 2 пары, вы хотите, чтобы тот, у которого меньшее значение для первого элемента, шел перед другим. Вы можете написать функцию сравнения так:

// This function returns true if the first pair is "less"
// than the second one according to some metric
// In this case, we say the first pair is "less" if the first element of the first pair
// is less than the first element of the second pair
bool pairCompare(const std::pair<double, Processor*>& firstElem, const std::pair<double, Processor*>& secondElem) {
  return firstElem.first < secondElem.first;

}

Теперь передайте эту функцию в метод сортировки:

//The sort function will use your custom comparator function 
std::sort(baryProc.begin(), baryProc.end(), pairCompare);
person maditya    schedule 07.08.2013
comment
+1 хороший пример исключения сравнения .second из обычного меньшего оператора std::pair. Я бы предпочел для этого функтор (скорее встроенный), но функциональное решение, тем не менее, работает. - person WhozCraig; 08.08.2013
comment
Спасибо за это хорошее объяснение. Я думаю, что стандартный компаратор будет работать нормально. Будет ли стандартный оператор сортировать правильно, если двойные значения часто совпадают? например: (1,proc1), (1,proc2), (2,proc3), (3,proc4), (3,proc5),.... - person user2633791; 08.08.2013
comment
@ user2633791 Вы спрашиваете, является ли сортировка стабильной. Алгоритм сортировки стабилен, если два элемента с одинаковым значением остаются в том же порядке относительно друг друга в конце сортировки, что и в начале. Алгоритм сортировки по умолчанию не является стабильным, но STL обеспечивает стабильную сортировку, которая подходит ваши цели. - person maditya; 08.08.2013
comment
Спасибо. теперь отлично работает со стандартным компаратором, если вы используете мой собственный компаратор, мой компилятор говорит: этот вызов функции пропускает список аргументов, эти указатели меня погубят :) - person user2633791; 08.08.2013
comment
@maditya есть идеи, почему мой компилятор так сказал? Отсутствуют аргументы для этого вызова функции. используйте &pairCompare вместо pairCompare, чтобы получить указатель на этот элемент. но это не помогает - person user2633791; 08.08.2013
comment
@user2633791 user2633791 В аргументах функции были лишние символы «›», теперь я их удалил. Я думаю, что это, вероятно, была проблема. (Должно быть std::pair<double, Processor*>, а не std::pair<double, Processor*>>) - person maditya; 08.08.2013
comment
да, я заметил это раньше... к сожалению, это не ошибка :( - person user2633791; 08.08.2013
comment
@user2633791 user2633791 Не уверен, извините... у меня компилируется - person maditya; 08.08.2013

#include <algorithm>

int main(){

    std::vector<std::pair<double,Processor*>> baryProc;

    std::sort(baryProc.begin(),baryProc.end());
}

Обратите внимание, что вам не нужен пользовательский компаратор, потому что компаратор по умолчанию для пары делает то, что вы хотите. Сначала он сравнивает первый элемент, и если они идентичны, он сравнивает второй элемент в паре.

person Hossein Nasr    schedule 07.08.2013
comment
Это будет работать, если значения double гарантированно уникальны (фактически это набор). Но без такой гарантии (принудительно если надо) компаратор писать надо. Компаратор по умолчанию для pair обычно выполняет return (a.first < b.first || (a.first == b.first && a.second < b.second; Последнее представляет собой сравнение указателей, которое укусит вас за неуникальные значения для first. - person WhozCraig; 08.08.2013
comment
у нас нет условия, которое помогло бы нам, что делать, когда первые элементы совпадают. так что произойдет, если мы используем компаратор по умолчанию? - person Hossein Nasr; 08.08.2013
comment
Почему вы указали std::vector и std::pair, а не std::sort? Если бы вы это сделали, вы могли бы полностью избавиться от бита using namespace std. - person Kevin; 08.08.2013
comment
@hoosssein Смотрите мой комментарий. оператор "меньше чем" по умолчанию (вызывается std::less<> для std::pair<> может и будет при необходимости нажимать оба значения (как правило, как я описал). Решение состоит в том, чтобы предоставить пользовательский компаратор, как показала Мадитья. - person WhozCraig; 08.08.2013
comment
нет причин. я просто копирую вопрос формы объявления переменной. спасибо за ваше замечание. - person Hossein Nasr; 08.08.2013
comment
До тех пор, пока вы понимаете, что для идентичных значений double состояние "меньше чем" теперь основано на сравнении двух указателей, что, безусловно, является тем, чего вы НЕ хотите (на самом деле это редко, так что ). - person WhozCraig; 08.08.2013
comment
так я понимаю, это моя причина непоследовательности в сортировке? или вы просто беспокоитесь о простом сравнении двух указателей, которые вызывают не более 5 часов процессора? - person Hossein Nasr; 08.08.2013
comment
Если два указателя не указывают на один и тот же массив или один за его концом, сравнение не определено. Если пользователь хочет упорядочить пары по первому элементу, то в этом случае он должен только сравнивать первые элементы. - person Blastfurnace; 08.08.2013
comment
почему стандартный компаратор здесь принимает двойные значения пары? - person user2633791; 08.08.2013
comment
@user2633791 user2633791 стандартный компаратор сравнивает лексикографически, используя first первое и second второе. Почему? Потому что это имеет смысл. - person juanchopanza; 08.08.2013
comment
как сказано, сначала он использует первый элемент (pair.first), затем использует второй элемент в паре (pair.second) для сравнения с парами любого типа. - person Hossein Nasr; 08.08.2013