Функция сортировки из стандартной библиотеки выдает ошибку с помощью итератора - PullRequest
0 голосов
/ 26 мая 2020

Я относительно новичок в языке C ++ и пытаюсь реализовать функцию сортировки из библиотеки алгоритмов, определенной в стандартном пространстве имен, и напрямую использовать std :: sort. Общая структура для сортировки вектора с использованием сортировки задается с использованием итератора и функции сравнения.

Рассмотрим вектор v as {4,3,5,9}, и после сортировки он будет выглядеть как {9,5,4,3}. Для экземпляра

 std::sort(v.begin(),v.end(),a>b)

Итак, я хотел использовать этот метод для сортировки списка узлов на основе значения heuristi c для моего алгоритма поиска A *. Heuristi c - это в основном добавление 2 атрибутов объекта Node, и операция сортировки должна быть выполнена вектор этих узлов, и я хочу использовать

open_list.begin() and open_list.end() as my iterators 

, чтобы использовать мою функцию сравнения в качестве третьего аргумента для функции std :: sort (), вот фактическая реализация:

std::sort(open_list.begin(),open_list.end(),open_list.begin()->g_value + open_list.begin()->h_value > open_list.end()->g_value + open_list.end()->h_value ); 

Здесь , Я в основном добавляю значения h и g, которые являются атрибутами объекта Node, а open_list - вектор указателей на узлы. Я чувствовал, что моя реализация верна, но это вызывает у меня странную ошибку, которая выглядит примерно так:

/ home / piyushkumar / CppND-Route-Planning-Project / src / route_planner. cpp: 65: 93: ошибка: запрос члена 'h_value' в ' ((RoutePlanner ) this) -> RoutePlanner :: open_list.std :: vector :: begin () .__ gnu_cxx :: __ normal_iterator> :: operator- > () ', который имеет тип указателя' RouteModel :: Node * '(возможно, вы имели в виду использовать' -> '?) std :: sort (open_list.begin (), open_list.end (), open_list.begin ( ) -> g_value + open_list.begin () -> h_value> open_list.end () -> g_value + open_list.end () -> h_value);

Некоторые пояснения относительно ошибки: RouteModel - это класс, а Node наследуется от этого класса. Почему эта простая функция сравнения в качестве третьего аргумента не работает и говорит, что вы должны использовать ->, который я уже использовал для получения значений g_value и h_value из объекта Node.

Любая помощь и предложения будут оценены.

Ответы [ 2 ]

1 голос
/ 26 мая 2020

Хорошо, здесь все не так.

Третий параметр std::sort - это «вызываемый» (как указатель на функцию), который std::sort вызывает для сравнения двух элементов в последовательности. Он должен взять два элемента последовательности (обычно const & и вернуть логическое значение.

Ваш пример std::sort(v.begin(),v.end(),a>b) не будет работать, потому что a>b не вызывается.

Ваш «настоящий» код страдает той же проблемой.

std::sort(open_list.begin(),
          open_list.end(),
              open_list.begin()->g_value + open_list.begin()->h_value >
              open_list.end()->g_value +   open_list.end()->h_value ); 

Это большое выражение не вызывается, а это причина того, почему компилятор жалуется.

Кроме того, FWIW, open_list.end() является итератором для позиции «один за концом» в последовательности, и разыменование его (как в open_list.end()->g_value) является неопределенным поведением, поскольку там нет элемента.

См. cppreference для получения дополнительной информации.

0 голосов
/ 26 мая 2020

Хорошо, давайте разберемся во всем по порядку.

Сначала о вашем сообщении об ошибке. Ваш вектор хранит указатели и имейте в виду, что a->b эквивалентно (*a).b, поэтому open_list.begin()->h_value равно open_list.front().h_value, а указатель явно не имеет переменной-члена. Чтобы обратиться к переменной-члену, нужно написать (*open_list.begin())->h_value. Более того, разыменование .end() сразу дает неопределенное поведение. Чтобы получить доступ к последнему элементу std::vector, используйте .back() вместо *(you_vector.end()). (Не забудьте заранее проверить, что вектор не пуст! В противном случае вы снова войдете в неопределенное поведение :))

Во-вторых, ваше представление о том, как использовать std::sort, неверно. Чтобы отсортировать диапазон элементов по «стандарту», ​​который вы выбрали, первые два параметра сортировки предоставляют информацию о диапазоне, а третий параметр - ваш «стандарт», поэтому он должен быть «вызываемым», и для этого требуется два параметры и указать std::sort, следует ли отсортировать первый параметр перед вторым. В результате, чтобы отсортировать v в порядке убывания, вам нужно вызвать std::sort следующим образом:

std::sort(v.begin(), v.end(), [](int a,int b)->bool{ return a > b;});

Здесь третий параметр - это лямбда-выражение, если вы не знаете, что это такое, гугл вам поможет. (Вызываемый FYI не обязательно может быть лямбда-выражением, он также может быть функцией или функтором (также известным как объект-функция), но я лично считаю, что лямбда здесь наиболее ясна.) необходимо для сортировки вашего open_list, вы можете использовать его, чтобы проверить, поняли ли вы, как все работает или нет. Наслаждайтесь обучением.

...