Как уже указывалось immibis :
Обратите внимание, что сортировка двумерного массива аналогична сортировке обычного одномерного массива, в котором сортируемые элементы являются массивами.
Я хотел бы добавить, что OP, мы надеемся, знает, что двумерный массив (массив массивов) - это не то, что было открыто OP.
double **stored_points
- указатель на double*
и может представлять массив double*
. Это не совместимый тип, например, double points[][2]
. (В SO много вопросов и ответов по этому поводу:
SO: Почему мы не можем использовать двойной указатель для представления двумерных массивов?
на самом деле помечен c , но также относится к c ++ .)
Стандартная библиотека уже предоставляет готовый std::sort()
для сортировки различных контейнеров (включая массивы), которые можно использовать в большинстве распространенных случаев & ndash; один из OP включительно:
Сортирует элементы в диапазоне [первый, последний) в порядке возрастания. Порядок равных элементов не гарантируется для сохранения.
Предоставленная сложность std::sort()
- это O (N & middot; log (N)) & rarr; намного лучше, чем сложность Bubble sort (OP считается использованным), который равен O (N²).
Доступно несколько вкусов. В случае OP требуется специальный компаратор, так как значение по возрастанию может быть изменено по запросу.
Следовательно,
template< class RandomIt, class Compare >
void sort( RandomIt first, RandomIt last, Compare comp )
выбрано.
Параметры
первый, последний - диапазон сортируемых элементов
comp - объект функции сравнения (т. Е. Объект, который удовлетворяет требованиям Compare), который возвращает значение true, если первый аргумент меньше (т. Е. Упорядочен раньше) второго.
Подпись функции сравнения должна быть эквивалентна следующей:
bool cmp(const Type1 &a, const Type2 &b);
Хотя подпись не обязательно должна иметь const &, функция не должна изменять переданные ей объекты и должна иметь возможность принимать все значения типа (возможно, const) Type1 и Type2 независимо от категории значения (таким образом, Type1 & не допускается и не является Type1, если только для Type1 перемещение не эквивалентно копии (начиная с C ++ 11)).
Типы Type1 и Type2 должны быть такими, чтобы объект типа RandomIt мог быть разыменован, а затем неявно преобразован в оба из них.
Для double **stored_points
, в first
stored_points
может быть передано, в last
stored_points + n
. Таким образом, n
- это размер массива. Это не упоминается в открытом коде OP, но это абсолютно необходимое значение. Указатель может представлять массив любой длины. Я знаю только два способа получить длину массива из указателя: либо предоставить его отдельно, либо использовать определенное значение в качестве конечного маркера (как это делается в строках C с '\0'
).
Для компаратора должна быть передана функция (или функтор) с соответствующей сигнатурой.
В данном конкретном случае это
bool(double* const &, double* const &)
но (еще лучше)
bool(double*, double*)
тоже подойдет.
Это может быть функция, функтор (то есть класс с operator()
) или лямбда (которая напоминает одну из первых). Я решил использовать лямбду (чтобы мой код был минимальным):
[](double *pt1, double *pt2) {
return pt1[0] != pt2[0] // if first elements unequal
? pt1[0] < pt2[0] // return whether first first < second first
: pt1[1] < pt2[1]; // else whether first second < second second
}
Это обеспечивает меньший оператор сравнения первого подэлемента, учитывая второй подэлемент, только если первый равен. Этот меньший компаратор определяет Order , который необходим в std::sort()
для определения значения по возрастанию.
Чтобы изменить порядок (для сортировки с ведущими координатами y), используется просто другая лямбда:
[](double *pt1, double *pt2) {
return pt1[1] != pt2[1] // if second elements unequal
? pt1[1] < pt2[1] // return whether first second < second second
: pt1[0] < pt2[0]; // else whether first first < second first
На самом деле выглядит довольно схожим образом только индексы поменялись местами.
Полный пример:
#include <algorithm>
#include <iostream>
#include <sstream>
#include <string>
// a print function (usable in output streams)
std::string print(double **data, size_t n)
{
std::ostringstream out;
const char *sep = "";
for (size_t i = 0; i < n; ++i) {
out << sep << '(' << data[i][0] << ", " << data[i][1] << ')';
sep = ", ";
}
return out.str();
}
int main()
{
// sample data of OP
double points[][2] = {
{ 1, 5 }, { 2, 2 }, { 1, 1 }, { 1, 3 }
};
const size_t n = sizeof points / sizeof *points; // let compiler determine
// resemble input data of OP
double *stored_points[n];
for (size_t i = 0; i < n; ++i) stored_points[i] = points[i];
// show input data
std::cout
<< "Input data:\n"
<< " " << print(stored_points, n) << '\n';
// sort in ascending order with leading x:
std::sort(stored_points, stored_points + n,
[](double *pt1, double *pt2) {
return pt1[0] != pt2[0] // if first elements unequal
? pt1[0] < pt2[0] // return whether first first < second first
: pt1[1] < pt2[1]; // else whether first second < second second
});
// show result
std::cout
<< "Data sorted by leading x:\n"
<< " " << print(stored_points, n) << '\n';
// sort in ascending order with leading y:
std::sort(stored_points, stored_points + n,
[](double *pt1, double *pt2) {
return pt1[1] != pt2[1] // if second elements unequal
? pt1[1] < pt2[1] // return whether first second < second second
: pt1[0] < pt2[0]; // else whether first first < second first
});
// show result
std::cout
<< "Data sorted by leading y:\n"
<< " " << print(stored_points, n) << '\n';
// done
return 0;
}
Выход:
Input data:
(1, 5), (2, 2), (1, 1), (1, 3)
Data sorted by leading x:
(1, 1), (1, 3), (1, 5), (2, 2)
Data sorted by leading y:
(1, 1), (2, 2), (1, 3), (1, 5)
Демонстрация в реальном времени на coliru