2015-06-16 3 views
0

Я пытаюсь сортировать вектор указателей на класс A, используя std :: sort, но у меня есть некоторые трудности.Сортировка вектора указателей по двум параметрам

Представьте себе, что существа класса A представляют собой точку, содержащую координаты x и y. Я хочу отсортировать вектор по координатам y от самого большого до самого низкого, используя некоторое фиксированное значение смещения. И, кроме того, я хочу сортировать его по координате x, от самого низкого до самого большого. У меня было что-то вроде в виду следующее, но, как вы можете себе представить, он не работает, как хотелось:

bool A::sortByCoordinates(const A *a, const A *b) 
{ 
    if ((b->y < a->y - offset) || (b->y > a->y + offset)) { 
     return false; 
    } else if (b->x < a->x) { 
     return true; 
    } 

    return false; 
} 


void A::recalculate(std::vector<A *> &test) 
{ 
    std::sort(test.begin(), test.end(), sortByCoordinates); 
} 

Короче говоря, если b->y < a->y - offset или b->y > a->y + offset лечить его как b->y == a->y, а затем сортировать по их координаты х от самого низкого до самой большой. Если приведенное выше значение неверно, введите b->y < a->y.

Как я могу это достичь?

РЕДАКТИРОВАТЬ:

Представьте плоскости ху, такие как это: plane

, где черные точки представляют собой класс А с координатами х и у. Я хочу разбить эту плоскость на конечное число секций, которые представлены красными линиями и широкими, как offset. Теперь я хочу рассматривать точки в этих разделах, поскольку они имеют одну и ту же координату y и сортируют их только по их координате x.

ответ

1
(b->y < a->y - offset) || (b->y > a->y + offset) 

Это два разных случая, которые должны иметь разные результаты. Я полагаю, что b «меньше» тогда a в первом случае, а «больше» в другом случае, но ваш код возвращает false для обоих случаев. См. Ответ Джонатана о том, как это исправить.


Но также отметить, что ваш подход (с учетом всех у это, что отличаются менее чем offset равно) имеет существенный недостаток: он не будет генерировать strict total order. Предположим, у вас есть offset=3 и три очка A(x=0,y=0), B(x=-2,y=2) и C(x=-4,y=4).

Вы будете иметь A и B попадающие в offset от y координат, так что вы будете сравнивать A.x и B.x и получить A<B. Аналогичным образом вы получаете B<C, но A и C не попадают в offset расстояние, поэтому вы получаете A>C, то есть A<B<C<A, чего никогда не должно быть. (Подтвердите координаты, если я ошибаюсь в вашем заказе). Поэтому вам сначала нужно пересмотреть свою концепцию заказа.


Если (как указывается в редактировании) необходимо разделить на горизонтальные полосы, и сортирует точки в пределах полосы по х, то вы не должны проверить, различаются ли y s не более чем offset, потому что две точки могут иметь свои y s отличаются менее чем offset, но все равно будут расположены в разных полосах. Я бы предложил явно рассчитать номер полосы и сравнить их, что-то вроде

bool A::sortByCoordinates(const A& a, const A& b) 
{ 
    // get stripe numbers, assuming A::y to be positive int 
    int stripeA = a.y/offset; // be careful if a.y can be negative! 
    int stripeB = b.y/offset; 
    if (stripeA != stripeB) 
     return stripeA < stripeB; 
    return a.x < b.x; 
} 
+0

x, y и смещение - целые числа. Может ли ваш код быть упрощенным, зная это? – user1806687

+0

@ user1806687, см. Править, но будьте осторожны, поскольку 'operator /' for 'int' имеет странное поведение вокруг нуля, поэтому вам, скорее всего, придется добавить отдельный 'if' для отрицательных (или положительных) чисел. – Petr

+0

Не беспокойтесь, все они всегда положительные и больше 0. Я попробую ваш код позже. – user1806687

Смежные вопросы