0

我有一个大小为 2 的 n 个双精度数组:

double **stored_points_;

我需要编写一个函数,根据给定的轴(x 或 y)按升序对这些坐标进行排序,并将这些排序后的坐标存储在一个新的二维数组中。我还需要一个函数来计算坐标的边界框并存储在两个给定的输出参数中。

我已经成功编写了复制构造函数、getter、setter 等。我尝试过一种冒泡排序,但不知道如何使它与二维数组一起工作。

我期望的是

如果坐标是 (1,5), (2,2), (1,1), (1,3) 当轴 = 0 时结果:(1,1), (1,3), (1,5), (2,2) 轴 = 1 时的结果:(1,1), (2,2), (1,3), (1,5)

//function definitions from class Points2D{}:

void SortByAxis(size_t axis, double** sorted_points) const;
//axis: 0 means sort by x-axis, 1 means sort by y-axis

void CalcBoundingBox(double lower_left[2], double upper_right[2])     const;

//some members of class Points2D{}:

public:
  static const size_t x = 0;
  static const size_t y = 0;
private:  0;
  double **stored_points_;
4

1 回答 1

3

正如immibis已经指出的那样:

请注意,对二维数组进行排序与​​对普通一维数组进行排序相同,其中您要排序的项目恰好是数组。

我想补充一点,希望 OP 知道 2D 数组(数组数组)不是 OP 公开的。

double **stored_points是一个指针double*,可以表示一个数组double*。这不是与 eg 兼容的类型double points[][2]。(SO 中有很多关于此的 Q/As:
SO:为什么我们不能使用双指针来表示二维数组?
实际上是用标记的,但也适用于。)

标准库已经提供了一个准备好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 现场演示

于 2019-06-20T08:20:10.270 回答