正如immibis已经指出的那样:
请注意,对二维数组进行排序与对普通一维数组进行排序相同,其中您要排序的项目恰好是数组。
我想补充一点,希望 OP 知道 2D 数组(数组数组)不是 OP 公开的。
double **stored_points是一个指针double*,可以表示一个数组double*。这不是与 eg 兼容的类型double points[][2]。(SO 中有很多关于此的 Q/As:
SO:为什么我们不能使用双指针来表示二维数组?
实际上是用c标记的,但也适用于c++。)
标准库已经提供了一个准备好std::sort()对各种容器(包括数组)进行排序的工具,这些容器可以在最常见的情况下使用——包括 OP 的容器:
按升序对范围 [first, last) 中的元素进行排序。不保证保留相等元素的顺序。
授予的复杂度std::sort()为 O(N·log(N)) → 比冒泡排序(考虑使用的 OP)的复杂度 O(N²) 好得多。
有多种口味可供选择。对于 OPs 情况,需要自定义比较器,因为升序的含义应根据要求更改。
因此,
template< class RandomIt, class Compare >
void sort( RandomIt first, RandomIt last, Compare comp )
被选中。
参数
first, last - 要排序的元素范围
comp - 比较函数对象(即满足比较要求的对象),如果第一个参数小于(即排在前面)第二个参数,则返回真。
比较函数的签名应该等同于以下内容:
bool cmp(const Type1 &a, const Type2 &b);
虽然签名不需要 const &,但该函数不得修改传递给它的对象,并且必须能够接受所有类型(可能是 const)Type1 和 Type2 的值,而不管值类别如何(因此,不允许使用 Type1 & , Type1 也不是,除非 Type1 的移动等价于副本 (C++11 起))。Type1 和 Type2 类型必须使得 RandomIt 类型的对象可以被取消引用,然后隐式转换为它们两者。
因为double **stored_points, infirst stored_points可以通过, in last stored_points + n。因此,n是数组的大小。OP 公开的代码中没有提到它,但它是绝对必要的值。指针可以表示任意长度的数组。我只知道从指针获取数组长度的两种方法:单独提供它或使用特定值作为结束标记(就像在 C 字符串中用 完成一样'\0')。
对于比较器,必须传递具有匹配签名的函数(或函子)。在这种特定情况下,它是
bool(double* const &, double* const &)
但是(甚至更好)
bool(double*, double*)
也会这样做。
这可以是一个函数、一个仿函数(即带有 的类operator())或 lambda(类似于前者)。我决定使用 lambda(以保持我的代码最小化):
[](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
}
这提供了一个比较第一个子元素的较少运算符,仅当第一个子元素相等时才考虑第二个子元素。这个较少的比较器定义了定义升序std::sort()含义所需的顺序。
要更改顺序(用于使用前导 y 坐标进行排序),只需使用另一个 lambda:
[](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 现场演示