2016-11-28 5 views
0

Если у меня есть структура POINT в C с координатами x и y, то какой приемлемый способ сортировать ее по первому элементу пары и то вторым, если первые равны? Я нашел много ответов на этом в C++, но не в C..может вам помочь?Сортировка вектора пар по первому элементу, а затем по второму элементу пары в C

+0

Возможно, что-то, что вы нашли для [tag: C++], можно использовать с [tag: c]. Кстати, это слишком широкий вопрос для SO. – LPs

+1

Просто используйте 'qsort' и соответствующую функцию сравнения - см. [Man qsort] (https://linux.die.net/man/3/qsort). –

+0

Для C++ он использовал некоторые вещи, которые не в C и Im, а не как опытный программист, чтобы «преобразовать» его из C++ в C, чтобы вы могли мне помочь? –

ответ

-1

Есть несколько ответов уже, но их реализация кажется слишком сложным,)

struct pair 
{ 
    int x; 
    int y; 
}; 

static inline int safe_cmp(int x, int y) 
{ 
    return (x > y) - (x < y); 
} 

int lex_cmp_pairs(const void *left, const void *right) 
{ 
    const struct pair *l = left; 
    const struct pair *r = right; 
    const int cmp_x = safe_cmp(l->x, r->x); 
    const int cmp_y = safe_cmp(l->y, r->y); 
    return (cmp_x == 0) ? cmp_y : cmp_x; 
} 

/* example usage: */ 
struct pair ps[] = { {3, 3}, {2, 5}, {1, 1}, {2, 2}, {1, 2}, {3, 1} }; 
qsort(ps, 6, sizeof(struct pair), lex_cmp_pairs); 

Обратите внимание, что вы, вероятно, захотите использовать qsort_r (расширение GNU), если вы собираетесь сортировать в потоковой среде.

+2

Использование вычитания для сравнения - очень плохая практика. Попробуйте это с помощью вашей функции: создайте две структурные точки, установите оба x в 0, установите a.y = INT_MAX, b.y = -1. Теперь b больше, чем a в вашей функции. установите a.y в INT_MAX - 1, и он станет меньше. Эта функция сравнения не транзитивна. Кроме того, неопределенное поведение через целочисленное нижнее значение, если все становится слишком маленьким. – Art

+0

Вы правы (+1 к вам для определения его) - исправлено путем введения безопасного сравнения (но все же без введения ненужного разветвления). –

+0

@PatrykObara: 'qsort_r' используется для передачи контекста функции сравнения, не прибегая к глобальной переменной, которая лучше подходит для потокового приложения, хотя вы можете использовать глобальную переменную с локальным хранилищем протектора. Здесь нет необходимости, поскольку функция сравнения использует только данные входа. – chqrlie

5

Просто используйте qsort и соответствующую функцию сравнения, например.

// point type 

typedef struct { 
    int x; 
    int y; 
} Point; 

// point compare function 

int compare_points(const void *p1, const void *p2) 
{ 
    const Point *pt1 = p1; 
    const Point *pt2 = p2; 

    // do primary compare on x 
    if (pt1->x > pt2->x) 
     return 1; 
    if (pt1->x < pt2->x) 
     return -1; 

    // pt1->x == pt2->x - do secondary compare on y... 
    if (pt1->y > pt2->y) 
     return 1; 
    if (pt1->y < pt2->y) 
     return -1; 

    // pt1 == pt2 
    return 0;   
} 

// sort an array of points... 

qsort(points, num_points, sizeof(Point), compare_points); 

LIVE DEMO

+1

Спасибо, это именно то, что я искал :) –

+1

Нет необходимости бросать из 'void *' в более конкретный тип указателя. Кроме того, полагаться на подписанное целочисленное недоиспользование обычно не рекомендуется. – unwind

+0

@unwind: хорошая точка на приведениях - спасибо - ответ обновлен. Я сделаю логику сравнения немного более надежной в ближайшее время ... –

1

вы можете либо написать уникальный компаратор-функцию

int comparator(POINT* p1, POINT* p2) { 
    if (p1->x < p2->x) { 
     return -1; 
    } 
    if (p1->x > p2->x) { 
     return 1; 
    } 
    if (p1->y < p2->y) { 
     return -1; 
    } 
    if (p1->y > p2->y) { 
     return 1; 
    } 
    return 0; 
} 

и использовать его с любым нормальным рода-реализации,

или вы могли бы определить диапазоны ваши координаты (например, 0 < x < 100) с этим предположением можно объединить обе координаты в одной целое и использовать любой Int на основе сортировки-реализации

int createCombinedCoordinate(POINT* p1) { 
    return P1->x * 100 + p1->y; 
} 

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

  • Нет связанных вопросов^_^