使用指针数组对结构进行排序的函数出现问题

时间:2019-02-05 01:30:13

标签: c dictionary pointers

在这里,我对作业和代码中的问题有非常详细的说明。作业分为两部分,第一部分的代码有效,但第二部分的代码修改后不再起作用。

家庭作业:使用字典来保存人的名字和最快的运行时间(使用开放式哈希,即字典用哈希表表示,哈希表是具有B个元素的数组,其中每个元素数组是单元格类型元素的链接列表。哈希表使用哈希函数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(char name [],字典A)如果有人在字典中,则返回1,否则返回0。)

这部分应该正常工作。

现在,作业的下一部分:使用另一个指针数组按人员的跑步时间对其进行排序,该数组的第一个元素指向最快的人的数据,第二个元素指向第二个最快的人人等。

我的想法是制作另一个字典,我们称之为字典数组。 现在,在将一个新人的数据插入原始词典Ap的同时,我想调用另一个函数void Sort(celltype * Data,Dictionary * Array),该函数采用存储新人数据的单元格类型以及我们将在其中插入的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);
    }
}

(一切都一样,只是我在函数中添加了另一个参数,并在末尾添加了该位(单元格类型* send; ... Sort(send(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. 调用函数Sort / function参数时出现问题。我在理解指针时仍然遇到一些问题,因此我不确定如何解决它。

  2. 在修改DiInsert之前,代码的第一位有效。现在,在修改并添加了void Sort()之后,由于某种原因,有时它会将原始Dictionary Ap中的数据加倍,并将其保存在正确的第i个括号中,并且也保存在其他一些括号中。

    < / li>
  3. 它还会使Dictionary Array中的数据加倍。例如,如果我输入“ Mark”作为名称,并输入10.1作为时间,则h(Mark)= 15,因此它将Mark的数据保存在Dictionary Ap的第15个括号中。然后,它将Mark的数据保存在Dictionary Array的第0个括号中(这是应该的,因为Mark的数据是第一个输入的数据,并且他现在是最快的数据),但它也将其保存在第16个括号中。为什么?

1 个答案:

答案 0 :(得分:0)

您通常不能使用字典来存储排序结果,因为这些是为快速随机访问而不是排序访问而设计的数据结构。您应该使用一个数组并对数组进行排序。

但是,由于您已经在字典中拥有所有元素,因此生成数组然后进行排序将很简单。毕竟,因为这是一项家庭作业,所以我将概述这个想法,然后让您填写其余内容:

  1. 计算字典中celltype个元素的数量并将其存储到total_elements
  2. 分配一个名称为celltype *的长度为total_elements的类型sort_array的新数组
  3. 编写一个遍历字典的函数,并将每个celltype元素的地址添加到sort_array
  4. 编写一个比较函数,以名称sort_compare_func()来实现您要实现的排序顺序
  5. 使用sort_arraytotal_elementssort_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

希望这会有所帮助。