用于对二维坐标数组进行排序并计算边界框的C ++函数

时间:2019-06-20 00:30:47

标签: c++ pointers multidimensional-array

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

double **stored_points_;

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

我已经成功地编写了拷贝构造函数,getter,setter等。我试图进行一种冒泡排序,但无法弄清楚如何使其与2d数组一起使用。

我期望的是

如果坐标是(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_;

1 个答案:

答案 0 :(得分:2)

immibis已经指出:

  

请注意,对2D数组进行排序与​​对要排序的项目恰好是数组的普通1D数组进行排序相同。

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

double **stored_points是指向double*的指针,并且可以表示double*的数组。这不是兼容的类型,例如double points[][2]。 (SO中有许多与此相关的Q / A:
SO: Why can't we use double pointer to represent two dimensional arrays?
实际上被标记为,但也适用于。)

标准库已经提供了一个方便的std::sort()来对各种容器(包括数组)进行排序,这些容器可以在最常见的情况下使用-其中包括OP:

  

按升序对[first,last)范围内的元素进行排序。相等元素的顺序不能保证得到保留。

授予std::sort()的复杂度是O(N·log(N))→比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&,但该函数不得修改传递给它的对象,并且必须能够接受Type1和Type2类型的所有值(可能是const),而与值类别无关(因此,Type1&不允许,Type1也不允许,除非Type1的移动等效于一个副本(从C ++ 11开始)。   Type1和Type2类型必须使得可以取消引用RandomIt类型的对象,然后将其隐式转换为它们两者。

对于double **stored_points,可以在first stored_points中传递last中的stored_points + n。因此,n是数组的大小。在OPs公开代码中没有提到它,但这是绝对必要的值。指针可以代表任何长度的数组。我只知道两种从指针获取数组长度的方法:要么单独提供它,要么使用特定的值作为结束标记(就像在带有'\0'的C字符串中所做的那样)。

对于比较器,必须传递具有匹配签名的函数(或函子)。 在这种情况下,是

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()中需要的Order来定义升序的含义。

要更改顺序(用于对前导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)

Live Demo on coliru