Вопрос:
Я хотел бы знать, возможно ли сортировать число четным или нечетным с помощью функции std:: sort.
У меня есть следующие коды, но я не уверен, как реализовать в std:: sort
inline bool isEven(const Point n) { return n.getX()%2==0; }
Правильно ли это.
vector<Point> c; std::sort(c.begin(),c.end(),isEven)
Пожалуйста, совет.
Лучший ответ:
Из того, что я понимаю по вашему вопросу, вы хотите отделить числа odd и even. Если это произойдет, std::partition сделает именно это.
Если вы хотите отсортировать по восходящим значениям и отдельным номерам odd и even, я бы использовал нечто похожее на этот фрагмент кода (все же вам нужно будет выяснить, какой компонент вашего Point вы хотите для сортировки)
bool sortByEven(const int& left, const int& right) { if(left & 1 && right & 1) // both are odd { return left < right; } else if(left & 1) // left is odd { return false; } else if(right & 1) // right is odd { return true; } // both are even return left < right; }
Эта функция может использоваться с std::sort, здесь краткий пример:
std::vector<int> numbers; numbers.push_back(-1); numbers.push_back(5); numbers.push_back(12); numbers.push_back(7); numbers.push_back(-31); numbers.push_back(-20); numbers.push_back(0); numbers.push_back(41); numbers.push_back(16); std::sort(numbers.begin(), numbers.end(), sortByEven);
Выдает следующий результат:
-20 0 12 16 -31 -1 5 7 41
Для других типов просто измените int или сделайте его template параметром
Ответ №1
Для этого вы должны использовать std::partition вместо std::sort
vector<Point> c; std::partition(c.begin(),c.end(),isEven)
При сортировке вы обычно хотите, чтобы сортировка основывалась на относительном порядке любых двух элементов. В этом случае вы просто хотите разбить свой вход на основе неотъемлемого свойства ваших элементов. Оба случая могут быть сведены к другому, но всегда легче принять прямой подход.
Ответ №2
Если вы посмотрите на ссылку std::sort, вы увидите, что функция, которую она использует для сравнения, должна принимать два аргумента, которые она должна сравнивать, Таким образом, ваш код не будет работать вообще.
Я рекомендую вам вместо этого перебирать вектор, сортируя четные значения в один временный вектор, а нечетные значения – в другой временный вектор. Затем вы очищаете фактический вектор и добавляете два временных вектора в том порядке, который вам нравится.
Ответ №3
Вы можете написать функцию сравнения, например
bool evenOddLess( Point const& a, Point const& b ) { return (isEven( a ) < isEven( b )); }
Затем вы можете использовать это как третий аргумент для std::sort.
Ответ №4
В С# это еще проще:
class Program { static void Main() { int[] numbers = { 1, 2, 3, 4, 5,6,7,8,9,10,11,12,13,14 }; //using delegate Array.Sort (numbers, (x, y) => x % 2 == y % 2 ? 0 : x % 2 == 1 ? -1 : 1); Array.ForEach(numbers, x => Console.Write(x)); Console.WriteLine(«»); //using custom comparer CustomComparer comparer = new CustomComparer(); Array.Sort(numbers, comparer); Array.ForEach(numbers, x => Console.Write(x)); Console.WriteLine(«»); //using lambda int[] items = numbers.OrderBy(x => x % 2 == 0).ThenBy(x => x % 2).ToArray(); Console.WriteLine(«»); Array.ForEach(items, x => Console.Write(x)); } public int Compare(int x, int y) { return x % 2 == y % 2 ? 0 : x % 2 == 1 ? -1 : 1; } } public class CustomComparer : IComparer<int> { int IComparer<int>.Compare(int x, int y) { return x % 2 == y % 2 ? 0 : x % 2 == 1 ? -1 : 1; } } Ответ №5
Уловка состоит в том, что есть две функции, которые вы можете использовать.
template< class BidirectionalIterator, class UnaryPredicate > BidirectionalIterator partition( BidirectionalIterator first, BidirectionalIterator last, UnaryPredicate p ); template< class BidirectionalIterator, class UnaryPredicate > BidirectionalIterator stable_partition( BidirectionalIterator first, BidirectionalIterator last, UnaryPredicate p );
Функции раздел() и stable_partition() реорганизовывать элементов коллекции таким образом, чтобы все элементы для который предикат p возвращает true, будет предшествовать всем тем, для который p возвращает false. Это означает, что элементы будут разделен на два диапазона:
• [first, return_value)
• [return_value, last)
где return_value – итератор, возвращаемый любой из функций. Последовательность элементов в результирующих группах partition() и stable_partition() отличаются.
partition() не гарантирует любой конкретный порядок в пределах диапазоны.
stable_partition() будет сохранять относительный порядок элементов до раскол. Это означает, что если есть два элемента a и b и a предшествует b, и если они оба принадлежат к одной и той же группе после раскола, элемент a по-прежнему будет предшествовать элементу b.
Вот пример кода:
#include <iostream> #include <algorithm> #include <vector> using namespace std; bool IsOdd(int i) { return (i & 1); //use !(i & 1); if you want to place even elements first in the vector } int main() { vector<int> v; // set some values and shuffle them: for (int i = 1; i<10; ++i) v.push_back(i); random_shuffle(v.begin(), v.end()); cout << «All elements:»; for (vector<int>::iterator it = v.begin(); it != v.end(); ++it) cout << ‘ ‘ << *it; cout << endl; //sort the vector cout << «Sorted vector:»; sort(v.begin(), v.end()); for (vector<int>::iterator it = v.begin(); it != v.end(); ++it) cout << ‘ ‘ << *it; cout << endl; //change to partition and see the difference vector<int>::iterator bound = stable_partition(v.begin(), v.end(), IsOdd); // print content: cout << «odd elements:»; for (std::vector<int>::iterator it = v.begin(); it != bound; ++it) cout << ‘ ‘ << *it; cout << endl; cout << «even elements:»; for (vector<int>::iterator it = bound; it != v.end(); ++it) cout << ‘ ‘ << *it; cout << endl; cout << «Sorted odd-even vector:»; for (vector<int>::iterator it = v.begin(); it != v.end(); ++it) cout << ‘ ‘ << *it; cout << endl; return 0; }
Вывод:
All elements: 5 6 2 1 9 4 7 8 3 Sorted vector: 1 2 3 4 5 6 7 8 9 odd elements: 1 3 5 7 9 even elements: 2 4 6 8 Sorted odd-even vector: 1 3 5 7 9 2 4 6 8
Я надеюсь, что это поможет понять.