Проблема с функцией, которая сортирует структуры, используя массив указателей - PullRequest
0 голосов
/ 05 февраля 2019

Здесь у меня есть действительно подробное объяснение моей домашней работы и проблем в коде.Есть две части домашнего задания, и код для первой части работает, но после изменения его для второй части он больше не работает.

Домашнее задание: Сохранить имя человека и самое быстрое время работы с помощью словаря (с открытым хешированием, то есть словарь представлен хеш-таблицей, которая представляет собой массив с элементами B, гдеЭлемент массива представляет собой связанный список элементов типа celltype. Хэш-таблица использует хеш-функцию h (name), где для i = 1, ..., B-1, если h (name) = i, то данные оперсона с «именем» сохраняется в связанном списке в i-м элементе словаря. Люди сортируются по имени.)

Вот как это выглядит.

#define B 20
typedef struct celltag{
    char name[11];
    double time;
    struct celltag *next;
} celltype;

typedef celltype **Dictionary;

int h(char name[]){
    int i, sum=0;
    for(i=0;name[i]!='\0';i++) {
        sum+=name[i];
    }
    return sum % B;
}

void DiMakeNull (Dictionary *Ap){
    int i;
    for(i=0;i<B;i++) (*Ap)[i]=NULL;
}

void DiInsert(char name[], double time, Dictionary *Ap){
    int bucket;
    celltype *oldheader;
    if(DiMember(name, *Ap)==0){
        bucket=h(name);
        oldheader=(*Ap)[bucket];
        (*Ap)[bucket]=(celltype*)malloc(sizeof(celltype));
        strcpy((*Ap)[bucket]->name, name);
        (*Ap)[bucket]->time= time;
        (*Ap)[bucket]->next=oldheader;
    }
}

(Функция DiMember (имя персонажа [], Словарь A) возвращает 1, если в словаре есть человек, и 0, если нет.)

Эта часть работает так, как должна.

Теперь следующаячасть домашнего задания: Сортировка людей по времени их выполнения с использованием другого массива указателей, где первый элемент массива указывает на данные самого быстрого человека, второй элемент - на второго самого быстрого человека и т. д.

Моя идея состояла в том, чтобы сделатьдругой словарь, давайте назовем его словарь массив.Теперь, вставляя данные нового человека в исходный словарь Ap, я хотел вызвать другую функцию void Sort (celltype * Data, Dictionary * Array), которая принимает тип ячейки, в которой хранятся данные нового человека, и массив, в который мы будем вставлятьэто отсортировано по времени.

Поскольку я использовал бы это в DiInsert, я изменил его на

void DiInsert(char name[], double time, Dictionary *Ap, Dictionary *Array){
    int bucket;
    celltype *oldheader;
    if(DiMember(name, *Ap, 0)==0){
        bucket=h(name);
        oldheader=(*Ap)[bucket];
        (*Ap)[bucket]=(celltype*)malloc(sizeof(celltype));
        strcpy((*Ap)[bucket]->name, name);
        (*Ap)[bucket]->time= time;
        (*Ap)[bucket]->next=oldheader;

        celltype *send;
        send=(*Ap)[bucket];
        send->next=NULL;
        Sort(send, Array);
    }
}

(Все то же самое, за исключением того, что я добавил еще один параметр в функцию и добавил этот бит (celltype *)send; ... Sort (send, Array);) в конце.)

А вот так выглядит функция:

void Sort(celltype* Data, Dictionary *Array){
     if ((*Array)[0]==NULL){
         (*Array)[0]=Data;
         (*Array)[0]->next=NULL;
     }

    else{
        int i;
        for(i=0;(*Array)[i]!=NULL;i++){
            if(Data->time < (*Array)[i]->time){
                celltype *new;
                new=(*Array)[i];
                (*Array)[i]=new;
                (*Array)[i]->next=NULL;
                int j=i+1;
                while((*Array)[j]!=NULL){
                    celltype *old;
                    old=(*Array)[j];
                    (*Array)[j]=new;
                    (*Array)[j]->next=NULL;
                    new=old;
                    j++;
                }
                (*Array)[j]=new;
                (*Array)[j]->next=NULL;
                break;
            }
        }
    }
}

Вот мои проблемы:

  1. Возникла проблема при вызове функции сортировки / параметров функции.У меня все еще есть некоторые проблемы с пониманием указателей, поэтому я не совсем уверен, как это исправить.

  2. Перед изменением DiInsert сработал первый бит кода.Теперь, после изменения и добавления void Sort (), по некоторым причинам он иногда удваивает данные в исходном словаре Ap и сохраняет их в правильной i-й скобке, но также и в некоторых других скобках.

  3. Также удваивает данные в массиве словаря.Например, если я введу 'Mark' как имя и 10.1 как время, h (Mark) = 15, то это сохранит данные Марка в 15-й скобке словаря Ap.Затем он сохраняет данные Марка в 0-й скобке в массиве словаря (как и должно быть, потому что данные Марка являются первыми введенными данными и являются самыми быстрыми на данный момент), но затем он также сохраняет их в 16-й скобке.Почему?

1 Ответ

0 голосов
/ 05 февраля 2019

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

Но поскольку у вас уже есть все элементы в словаре, будет просто сгенерировать массив и затем выполнить сортировку.Поскольку это домашнее задание, в конце концов, я просто набросаю идею и позволю вам заполнить остальные:

  1. подсчитайте количество celltype элементов в вашем словаре и сохраните его в total_elements
  2. выделить новый массив типа celltype * длины total_elements с именем sort_array
  3. написать функцию, которая просматривает ваш словарь и добавляет адрес каждого элемента celltypesort_array
  4. написать подходящую функцию сравнения, которая реализует порядок сортировки, которого вы хотите достичь, с именем sort_compare_func()
  5. запустить алгоритм сортировки на sort_array с total_elements, используя sort_compare_func()

Я не уверен, требует ли ваша домашняя работа реализации собственного алгоритма сортировки.Мой фрагмент кода будет использовать стандартную функцию POSIX qsort():

// compare function for sort algorithm
static int sort_compare_func(const void *a, const void *b) {
     // called with pointers to (celltype *) elements in array
     double timeA = (*(celltype **) a)->time;
     double timeB = (*(celltype **) b)->time;

     // <  0 : a faster than b
     if (timeA < timeB) return(-1);
     // >  0 : b faster than a
     if (timeB < timeA) return( 1);
     // == 0 : a same time as b
     return(0);
}
....

unsigned int total_elements = count_elements_in_dictionary(Ap);
celltype **sort_array       = malloc(total_elements * sizeof(celltype *));

// fill the array
fill_sort_array_from_dictionary(Ap, sort_array);

// sort_array[0]                  points to the first celltype element found in Dictionary
// sort_array[total_elements - 1] points to the last  celltype element found in Dictionary

// sort array using POSIX quick sort implementation
qsort(sort_array, total_elements, sizeof(celltype *), sort_compare_func);

// sort_array[0]                  points to the celltype element with the smallest time
// sort_array[total_elements - 1] points to the celltype element with the largest time

celltype *winner = sort_array[0];
printf("and the winner is: %s with %f\n", winner->name, winner->time);

Простой тестовый код: 100 элементов со случайным временем от 0 до 100:

#include <stdlib.h>
#include <time.h>

.... 
unsigned int total_elements = 100;
....
//fill_sort_array_from_dictionary(Ap, sort_array);
srand(time(NULL));
celltype *data = malloc(total_elements * sizeof(celltype));
for (int i = 0; i < total_elements; i++) {
   sprintf(data[i].name, "%04d", i);
   data[i].time  = (rand() * 100.0) / RAND_MAX;
   sort_array[i] = &data[i];
}
...

Некоторый тестработает:

$ gcc -Wall -o dummy dummy.c
$ ./dummy 
and the winner is: 0085 with 0.165149
and the looser is: 0066 with 99.612887
$ ./dummy 
and the winner is: 0044 with 0.484525
and the looser is: 0006 with 98.964099
$ ./dummy 
and the winner is: 0066 with 0.293111
and the looser is: 0016 with 99.822637

Надеюсь, это поможет.

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