Проблема реализации алгоритма сортировки в C с массивом структур - PullRequest
0 голосов
/ 04 апреля 2010

Ну вот моя маленькая проблема, сначала мой код:


struct alumn {
    char name[100];
    char lastname[100];
    int par;
    int nota;
};</p>

<p>typedef struct alumn alumn;</p>

<p>int bubble(alumn **arr, int length)
{
    int i,j;
    alumn *temp;</p>

<pre><code>for (i=0; i<=length-2; i++) {
    for (j=i+1; j<=length-1;j++) {
        if ((*arr)[i].nota > (*arr)[j].nota) {
            temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
        }
    }
}

}

int main (int argc, char ** argv) { Alumn * Alumns;

... here goes some other code ...

bubble(&alumns,totalAlumns);

return 0;

}

Моя проблема в том, что этот алгоритм ничего не сортирует. Мне тяжело делать своп, я все перепробовал, но ничего не работает :(. Любая помощь ???

Ответы [ 3 ]

5 голосов
/ 04 апреля 2010

Видимо, вы путаете массив структур выпускников с массивом указателей на alumm struct .

Логика Bubble поддерживает массив указателей, в результате чего основная функция, похоже, вызывает его с массивом структур.

Из-за размера структуры alumn, вероятно, более эффективно выполнять пузырьковую сортировку для указателей, поскольку каждый обмен требует гораздо меньшего перемещения данных (3 копии одного указателя по несколько байт каждая, по сравнению с 3 копии структуры alumn, 200+ байтов каждая!).

Я предлагаю вам изменить логику (не показанную во фрагменте вопроса) функции main (), чтобы ввести такой массив указателей на фактические структуры alumn. (Конечно, этот массив указателей не избавит вас и от размещения самих структур, внутри блока (в виде структуры) или по отдельности.


По вашей настойчивости я намекаю здесь, как может выглядеть main для создания массива указателей, используемых пузырьком (пузырь остается неизменным).
Кстати, я объявляю столбцы как alumn *alumns[], что показывает намерение использовать их с большей готовностью. это то же самое, что и alumn **alumns.

int main(int argc, char **argv)
{
    alumn *alumns[];   // changed to array of pointers [to alumn structs] 
                       // was pointer to alumn struct, likely to be used as an array thereof

    int MaxNbOfAlumns = some_limit;
    alumns = malloc(sizeof(*alumn) * MaxNbOfAlumns);

    // Load the alumn records (from file or whereever)
    // pseudo code:
    // int i_alumns = 0;  // points to the next free slot in alumns array
    // for each record (in file or whereever...)
    //     alumms[i_alums] = malloc(sizeof(struct alumn));
    //     strcpy(alumms[i_alums]->lastname,  whatever_data);
    //     strcpy(alumms[i_alums]->name,  whatever_otherdata);
    //     alumms[i_alums]->par = some_int_data;
    //     alumms[i_alums]->nota = some_other_int_data;
    //     i_alums++;

... here goes some other code ...

  bubble(alumns, totalAlumns);   // alumns now being an array can be passed as is.

  return 0;
}

В качестве альтернативы, если вы хотите сохранить исходную переменную alumns, как раньше, все, что может понадобиться, - это что-то подобное, непосредственно перед вызовом bubble ()

  int i;
  alumn *ap_alumns[];   // new variable
  ap_alumns = malloc(sizeof(*alumn) * totalAlumns);
  for (i = 0; i < totalAlumns; i++)
      ap_alums[i] = &alumns[i];
  bubble(ap_alumns, totalAlumns);  

Одна вещь, на которую следует обратить внимание, заключается в том, что независимо от происхождения, массив, передаваемый в bubble (), сортируется нормально, но для его использования необходимо разыменовать отдельные указатели.
При этом со старым массивом, который вы намеревались использовать, как, скажем, alumns[123].lastname, теперь вам потребуется alumns[123]->lastname (или ap_alumns[123]->lastname, если вы используете вторую версию).

0 голосов
/ 04 апреля 2010

Ваш код написан так, как будто у вас есть массив указателей, но вы пропустили важную часть вашего кода (например, ... here goes some other code ...), поэтому мы не можем видеть, как вы настроили сортируемую вещь , Если у вас есть массив указателей, эта строка кода:

if ((*arr)[i].nota > (*arr)[j].nota) {

должно быть:

if (arr[i]->nota > arr[j]->nota) {

Причина в том, что (* arr) получает первый указатель в списке, затем (* arr) [i] получает i-й элемент в памяти после этого указателя (бессмысленно, поскольку каждый указатель должен указывать на один элемент). Второй синтаксис переходит к i-му указателю в массиве указателей и разыменовывает его, чтобы получить это значение.

Может быть, эта иллюстрация поможет:

arr points to an array of two pointers, each pointing to a struct.
(*arr)[1].nota refers to an item in ??????.
arr[1]->nota refers to an item in struct 2.

       +---+                   +----------+
arr -> | * | ----------------> | struct 1 |
       +---+    +----------+   +----------+
       | * | -> | struct 2 |   :  ??????  :
       +---+    +----------+   +..........+
0 голосов
/ 04 апреля 2010

Ваш код не работает, потому что вместо массива указателей у вас есть массив структур.

Когда вы пытаетесь поменять две структуры, оператор = не знает, что делать. Вы должны скопировать поля структуры одно за другим, чтобы это работало.

Если у вас есть массив указателей на экземпляры структуры alumn. Тогда код будет работать, так как вы назначаете указатели. Указатель в основном число и = знает, как скопировать число.

...