【问题标题】:C++ Sort a vector of pointers in which the objects represent matrix coordinatesC++ 对指针向量进行排序,其中对象表示矩阵坐标
【发布时间】:2016-01-04 10:38:44
【问题描述】:

我读取了一个文件,其中一个矩阵填充了 0、1 和 2。 当我找到 1 时,我创建一个 BlueCar,当我找到 2 时,我创建 RedCar:

class BlueCar : public Car
{
    public:
        BlueCar(){};
        BlueCar(int x, int y);
        void move();
        virtual ~BlueCar();
};

class RedCar : public Car
{
    public:
        RedCar(){};
        RedCar(int x, int y);
        void move();
        virtual ~RedCar();
};

class Car
{
    public:
        Car();
        Car(int x, int y);
        virtual ~Car();
        virtual void move() = 0;

    private:
        int x,y;
};

我用这个对象填充两个向量:

    std::vector<BluCar*> *sparseBlu;
    std::vector<RedCar*> *sparseRed;

考虑到我需要移动矩阵的汽车,蓝色的汽车向下移动,红色的汽车向右移动,我认为最好的方法是对这些向量进行排序。这样我可以快速查看我正在考虑的汽车旁边的位置是否是空的。

由于蓝色汽车向下移动,我认为最好先按列再按行对“sparseBlu”进行排序,而不是先按行再按列对“sparseRed”进行排序。

我怎样才能达到这个结果? 最好是(就性能而言)当我一车一车地填充向量时立即对它进行排序,对吧?

【问题讨论】:

  • 首先,为什么要在向量中存储指针? std::vector&lt;BluCar&gt;std::vector&lt;RedCar&gt;。为什么向量指针本身呢? std::vector&lt;BluCar&gt; sparsBlu, std::vector&lt;RedCar&gt; sparsRed.
  • 两辆车去同一个坐标会发生什么?
  • @PaulMcKenzie 因为我不知道矩阵的大小是否适用于 ex。 10x10 或 100000x100000,所以我不想填满所有堆栈。
  • @Jarod42 他们不能去同一个坐标,因为红车有转弯,蓝车有转弯
  • @rh0x A std::vector 使用堆而不是堆栈来分配数据。您从哪里得到 std::vector 使用堆栈的想法? std::array&lt;T&gt; 使用基于堆栈的元素,而不是向量。

标签: c++ sorting matrix vector


【解决方案1】:

简答:

std::sort(std::begin(*sparseBlu), std::end(*sparseBlu),
          [](const BlueCar* lhs, const BlueCar* rhs) -> bool {
              return lhs->get_x() < rhs->get_x() ||
                     (lhs->get_x() == rhs->get_x() && lhs->get_y() < rhs->get_y());
          });

std::sort(std::begin(*sparseRed), std::end(*sparseRed),
          [](const RedCar* lhs, const RedCar* rhs) -> bool {
              return lhs->get_y() < rhs->get_y() ||
                     (lhs->get_y() == rhs->get_y() && lhs->get_x() < rhs->get_x());
          });

请重新考虑,如果使用指针真的是你需要的。没有指针,噪音会更小。

std::vector<BluCar> sparseBlu;
std::vector<RedCar> sparseRed;

std::sort(std::begin(sparseBlu), std::end(sparseBlu),
          [](const BlueCar& lhs, const BlueCar& rhs) -> bool {
              return lhs.get_x() < rhs.get_x() ||
                     (lhs.get_x() == rhs.get_x() && lhs.get_y() < rhs.get_y());
          });

std::sort(std::begin(sparseRed), std::end(sparseRed),
          [](const RedCar& lhs, const RedCar& rhs) -> bool {
              return lhs.get_y() < rhs.get_y() ||
                     (lhs.get_y() == rhs.get_y() && lhs.get_x() < rhs.get_x());
          });

当这种排序在您的应用程序中很自然时,您还可以考虑重载operator &lt; ()。这使得对sort() 的调用更加明确:

std::sort(std::begin(sparseBlu), std::end(sparseBlu), std::less<BlueCar>);
std::sort(std::begin(sparseRed), std::end(sparseRed), std::less<RedCar>);

几乎是声明式的编程风格。

如果您出于某种原因决定坚持使用指针,请考虑使用std::unique_ptr&lt;&gt;std::shared_ptr&lt;&gt; 而不是原始指针,以正确管理对象的生命周期。请记住,C++ 中没有垃圾收集。

【讨论】:

  • 比较方法可以使用:return std::make_tuple(lhs.get_x(), lhs.get_y()) &lt; std::make_tuple(rhs.get_x(), rhs.get_y());
  • @Jarod42 是的,谢谢。我只是有点担心,比较元组可能不够清楚地说明这里的意图。代码的读者可能会感到惊讶。作为operator &lt; () 的实现,我很感激你的方法。
  • @cdonat mmm...我想我不明白向量是如何工作的,所以我不需要指针
【解决方案2】:

std::sort 有一个带有比较器的重载版本 - 一个用于比较两个项目的自定义函数:http://en.cppreference.com/w/cpp/algorithm/sort,因此您可以指定任何比较。

您还可以考虑将您的汽车存储在一个稀疏矩阵 (std::vector&lt;std::vector&lt;Car&gt;&gt;) 中,其中空单元格就是空的。所以你不需要排序,如果它是空的,可以查看对应的单元格。

【讨论】:

  • 我不明白第二部分你说要使用 std::vector<:vector>>.... 我怎么会有一个空单元格?
  • 你不能。更重要的是,矩阵不会持有BlueCars 或RedCars - 只是Cars。这指针的情况。如果你有一个密集矩阵std::vector&lt;std::vector&lt;Car*&gt;&gt;,你可以多态地持有汽车,并且有空单元格。
  • 原始指针:在别处管理生命周期。如果这要管理生命周期,那么std::vector&lt;std::vector&lt;std::unique_ptr&lt;Car&gt;&gt;&gt;
猜你喜欢
  • 2020-09-17
  • 1970-01-01
  • 2021-09-20
  • 1970-01-01
  • 1970-01-01
  • 2014-03-11
  • 2016-07-06
  • 2014-12-29
  • 2017-09-14
相关资源
最近更新 更多