Сортировка вектора объектов - PullRequest
1 голос
/ 22 июня 2011

У меня есть вектор, заполненный некоторыми экземплярами вершинных объектов, и мне нужно отсортировать его по его 'x' и после него по его 'y' координатам.

vertex.h

#ifndef VERTEX_H
#define VERTEX_H 1

class Vertex
{
private:
  double __x;
  double __y;
public:
  Vertex(const double x, const double y);
  bool operator<(const Vertex &b) const;
  double x(void);
  double y(void);
};

#endif // VERTEX_H

vertex.cpp

#include "vertex.h"

Vertex::Vertex(const double x, const double y) : __x(x), __y(y)
{
}

bool Vertex::operator<(const Vertex &b) const
{
  return __x < b.x() || (__x == b.x() && __y < b.y());
}

double Vertex::x(void)
{
  return __x;
}

double Vertex::y(void)
{
  return __y;
}

run.cpp

#include <algorithm>
#include <stdio.h>
#include <vector>

#include "vertex.h"

void prnt(std::vector<Vertex *> list)
{
  for(size_t i = 0; i < list.size(); i++)
    printf("Vertex (x: %.2lf y: %.2lf)\n", list[i]->x(), list[i]->y());
}

int main(int argc, char **argv)
{
  std::vector<Vertex *> list;
  list.push_back(new Vertex(0, 0));
  list.push_back(new Vertex(-3, 0.3));
  list.push_back(new Vertex(-3, -0.1));
  list.push_back(new Vertex(3.3, 0));

  printf("Original:\n");
  prnt(list);

  printf("Sorted:\n");
  std::sort(list.begin(), list.end());

  prnt(list);

  return 0;
}

Что я ожидаю в качестве вывода:

Original:
Vertex (x: 0.00 y: 0.00)
Vertex (x: -3.00 y: 0.30)
Vertex (x: -3.00 y: -0.10)
Vertex (x: 3.30 y: 0.00)
Sorted:
Vertex (x: -3.00 y: -0.10)
Vertex (x: -3.00 y: 0.30)
Vertex (x: 0.00 y: 0.00)
Vertex (x: 3.30 y: 0.00)

Но на самом деле я получаю:

Original:
Vertex (x: 0.00 y: 0.00)
Vertex (x: -3.00 y: 0.30)
Vertex (x: -3.00 y: -0.10)
Vertex (x: 3.30 y: 0.00)
Sorted:
Vertex (x: 0.00 y: 0.00)
Vertex (x: -3.00 y: -0.10)
Vertex (x: -3.00 y: 0.30)
Vertex (x: 3.30 y: 0.00)

Я не знаю, что именно не так, любая идея?

Ответы [ 4 ]

6 голосов
/ 22 июня 2011

Вы храните Vertex * в контейнере, а не Vertex.Когда вы звоните std::sort, вы на самом деле сортируете значение указателей, а не самих предметов.

Если вам действительно нужно хранить указатели (в чем я сомневаюсь), выможно использовать обходной путь, подобный этому (непроверенный):

struct less_than_key {
    inline bool operator() (const Vertex*& v1, const Vertex*& v2) {
        return ((*v1) < (*v2));
    }
};
std::sort(list.begin(), list.end(), less_than_key());
1 голос
/ 22 июня 2011

Если вы хотите сэкономить, написав все эти классы самостоятельно (и нарушив правило двойного подчеркивания!), Вы можете использовать просто

std::vector< std::pair<float, float> >

и std::sort.По умолчанию парные лексикографически сравниваются (что вы и просили), поэтому вам не нужен дополнительный код.

1 голос
/ 22 июня 2011

Вы сортируете указатели, а не фактические объекты Vertex.Попробуйте это:

std::vector<Vertex> list;
list.push_back(Vertex(0, 0);
list.push_back(Vertex(-3, 0.3);
...

Т.е. избавиться от указателя в контейнере списка и новых в вызовах push_back.

0 голосов
/ 22 июня 2011

По какой-то причине вы хотите отсортировать абсолютные значения:
Попробуйте это:

bool Vertex::operator<(const Vertex &b) const
{
  return std::abs(__x) < std::abs(b.__x) || (std::abs(__x) == std::abs(b.__x) && std::abs(__y) < std::abs::(b.__y));
}

Примечание: вам не нужно вызывать b.x (), чтобы получить член другого объекта, когда вы того же класса. Вы можете просто получить доступ к другому участнику.

Примечание: Не используйте двойное подчеркивание в ваших идентификаторах. Не используйте префикс идентификаторов с подчеркиванием.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...