2013-09-27 6 views
3

У меня возникли проблемы с сортировкой 2D динамического массива struct.Как отсортировать 2D динамический массив структур

У меня есть-структуру:

typedef struct abc 
{ 
    int total; 
} abc; 

и динамический 2D массив:

list = (abc**)malloc(listSize * sizeof(abc*)); 
    for (int i = 0; i < listSize; i++) 
    { 
     list[i] = (abc*)malloc(listSize2* sizeof(abc)); 
    } 

Я хочу использовать алгоритм сортировки:

qsort(list, listSize, sizeof list[0], cmp); 

и функцию сравнения для qsort:

int cmp(const void *l, const void *r) 
{ 
    const abc *a = *(const abc **)l; 
    const abc *b = *(const abc **)r; 

    return a[0].total > b[0].total; 

} 

Но проблема в том, что, хотя я думаю, что это работает для небольшого списка (например, около 5 целых чисел), он не может правильно сортироваться, если список немного больше. Что мне делать с функцией cmp(), чтобы она работала правильно?

Кстати, мне нужно только отсортировать list[x][0], так как я добавлю другие элементы позже.

(I'm basing my sorting code from another Stackoverflow post)

+0

См [SSCCE] (http://SSCCE.org/) – wich

ответ

5

Измените функцию сравнения для:

int cmp(const void *l, const void *r) 
{ 
    const abc *a = *(const abc **)l; 
    const abc *b = *(const abc **)r; 

    return a[0].total - b[0].total; 

} 

Использование qsort ожидаемая функция сравнения должна возвращать отрицательное, если первое значение меньше положительной, если она больше и 0, если два значения равны.

EDIT: благодаря WhozCraig: если вы думаете, что может ударить по или переполнения, вы можете пойти на более безопасную версию:

int cmp(const void *l, const void *r) 
{ 
    const abc *a = *(const abc **)l; 
    const abc *b = *(const abc **)r; 

    if (a[0].total < b[0].total) { 
     return -1; 
    } else if (a[0].total > b[0].total) { 
     return 1; 
    } else { 
     return 0; 
    } 
} 
+1

Единственное, что проблематично в этом, заключается в том, что 'a [0] .total' уже является отрицательным числом и' b [0]. Это очень большое * положительное * число. Метод вычитания подлежит потоку (или переполнению, если знаки меняются на противоположные). – WhozCraig

+0

@WhozCraig на самом деле это хорошая точка :) –

+1

Да, это так. Вы также можете уйти с 'return (a WhozCraig

2

со следующей структурой:

typedef struct abc { 
    int total; 
} ABC; 

Сравнить функции могут быть простыми, как:

int cmp(const void *l, const void *r) 
{ 
    const ABC *a = (const ABC *) l; 
    const ABC *b = (const ABC *) r; 
    if (a->total == b->total) return 0; 
    return (a->total < b->total) ? -1 : 1; 
} 

используется, например, как:

ABC list[][4] = {{{5},{2},{0},{4}}, 
        {{7},{3},{9},{1}}, 
        {{8},{6},{5},{7}}, 
        {{2},{7},{9},{5}}}; 

qsort(list, 4 * 4, sizeof(ABC), cmp); 

for (int i = 0; i < 4; ++i) 
    for (int j = 0; j < 4; ++j) 
     printf("%d ",list[i][j].total); 

, который выводит: 0 1 2 2 3 4 5 5 5 6 7 7 7 8 9 9.

И в случае, если вы хотите отсортировать его только в пределах строки, вы можете сделать:

for (int i = 0; i < 4; ++i)     
    qsort(list[i], 4, sizeof(ABC), cmp); 

который даст вам: 0 2 4 5 1 3 7 9 5 6 7 8 2 5 7 9. В этом случае (сортировка по строкам) не имеет значения, сохраняется ли list в целом в одном блоке памяти или нет. Ни это не имеет значения, если оно было выделено динамически или нет :)

+0

в Кассиопеяне qsort функция сравнения не является логической, она возвращает отрицательное значение, положительное значение или 0. –

+0

@IvayloStrandjev: Да. Спасибо, я исправил это. Хотя предыдущая версия как-то сработала. – LihO

+0

@LihO Я видел ваш код перед редактированием после комментария Ивайло Странджева, и код действительно пытался его сортировать, но список все еще был беспорядок. Код после редактирования не работает по какой-то причине. Дает мне ошибку сегментации. – StarShire

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