简体   繁体   English

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

[英]Problem with a function that sorts structures using array of pointers

Here I have a really detailed explanation of my homework and the problems in the code. 在这里,我对作业和代码中的问题进行了非常详细的解释。 There are two parts of the homework, and the code for the first part works, but after modifying it for the second part, it doesn't work anymore. 作业分为两部分,第一部分的代码有效,但第二部分的代码修改后不再起作用。

The homework: Save the person's name and fastest running time using Dictionary (with open hashing, that is, Dictionary is represented with hash-table which is an array with B elements, where each element of the array is a linked list of elements of type celltype. Hash table is using hash function h(name) where for i=1,...,B-1, if h(name)=i, then data about the person with the 'name' is saved in the linked list in the i-th element of the Dictionary. People are sorted by their name.) 功课: 使用Dictionary (使用开放式散列来保存人的名字和最快的运行时间) (使用开放式哈希表示,Dictionary用hash-table表示,哈希表是一个包含B个元素的数组,其中该数组的每个元素都是类型元素的链接列表)哈希表使用哈希函数h(name),其中对于i = 1,...,B-1,如果h(name)= i,则有关具有“名称”的人的数据将保存在链接列表中在字典的第i个元素中。人们按其名字排序。)

Here's how it looks like. 这是它的样子。

#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;
    }
}

(Function DiMember(char name[], Dictionary A) returns 1 if person is in the dictionary, 0 if not.) (如果有人在词典中,则函数DiMember(char name [],字典A)返回1,否则返回0。)

This part works as it should. 这部分应正常工作。

Now, the next part of the homework: Sort the people by their running time using another pointer array, where the first element of the array points to the data of the fastest person, the second element to the second fastest person etc. 现在,完成作业的下一部分: 使用另一个指针数组按运行时间对人员进行排序,其中数组的第一个元素指向最快的人的数据,第二个元素指向第二个最快的人,依此类推。

My idea was to make another Dictionary, let's call it Dictionary Array. 我的想法是制作另一个字典,我们称之为字典数组。 Now, while inserting a new person's data into the original Dictionary Ap, I wanted to call another function void Sort(celltype *Data, Dictionary *Array) which takes celltype in which the new person's data is stored and the Array in which we will insert it sorted by the time. 现在,在将一个新人的数据插入原始词典Ap的同时,我想调用另一个函数void Sort(celltype * Data,Dictionary * Array),该函数采用存储新人数据的单元格类型以及我们将在其中插入的Array它按时间排序。

Because I would use this in DiInsert, I modified it into 因为我将在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);
    }
}

(Everything is the same, except I added another parameter into the function, and I added that bit (celltype *send; ... Sort(send, Array);) at the end.) (一切都一样,除了我在函数中添加了另一个参数,并在末尾添加了该位(celltype * send; ... Sort(send,Array);)。)

And this is how the function looks: 该函数的外观如下:

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;
            }
        }
    }
}

These are my problems: 这些是我的问题:

  1. There is a problem in the call of the function Sort/function parameters. 函数Sort / function参数的调用存在问题。 I still have some problems understanding pointers so I'm not really sure how to fix it. 我在理解指针时仍然遇到一些问题,因此我不确定如何解决它。

  2. Before modifying the DiInsert, the first bit of code worked. 在修改DiInsert之前,第一部分代码起作用了。 Now, after modifying and adding the void Sort(), for some reason it sometimes doubles the data in the original Dictionary Ap and saves it in the correct i-th bracket, but also in some other bracket as well. 现在,在修改并添加了void Sort()之后,由于某种原因,有时会将原始词典Ap中的数据加倍,并将其保存在正确的第i个括号中,也将其保存在其他一些括号中。

  3. It also doubles the data in the Dictionary Array. 它还会将字典数组中的数据加倍。 For example, if I input 'Mark' as name and 10.1 as time, h(Mark)=15, so it saves Mark's data in the 15-th bracket of the Dictionary Ap. 例如,如果我输入“ Mark”作为名称,并输入10.1作为时间,则h(Mark)= 15,因此它将Mark的数据保存在Dictionary Ap的第15个括号中。 Then, it saves Mark's data in the 0th bracket in the Dictionary Array (as it should, because Mark's data is the first data inputed and he's the fastest one for now) but then it ALSO saves it in the 16-th bracket. 然后,它将Mark的数据保存在Dictionary Array的第0个括号中(这是应该的,因为Mark的数据是第一个输入的数据,并且他现在是最快的数据),但它也将其保存在第16个括号中。 Why? 为什么?

You usually can't use a dictionary for storing sorted results, because those are data structures designed for fast random access, not sorted access. 通常,您不能使用字典来存储排序结果,因为这些是为快速随机访问而不是排序访问而设计的数据结构。 You should use an array and sort that array. 您应该使用一个数组并对数组进行排序。

But as you already have all elements in the dictionary it will be simple to generate the array and then do the sort. 但是由于您已经在字典中拥有所有元素,因此生成数组然后进行排序将很简单。 As this is a homework, after all, I'll onlu sketch the idea and let you fill out the rest: 毕竟,因为这是一项家庭作业,所以我将概述这个想法,然后让您填写其余内容:

  1. count the number of celltype elements in your dictionary and store it to total_elements 算的数celltype在你的字典元素,并将其存储到total_elements
  2. allocate a new array of type celltype * of length total_elements with name sort_array 分配一个新的类型为celltype *的数组,其长度为total_elements ,名称为sort_array
  3. write a function that goes through your dictionary and adds the address of each celltype element to sort_array 写,通过你的字典去,并增加了每个地址的功能celltype元素sort_array
  4. write a comparison function suitable that implements the sorting order you want to achieve with the name sort_compare_func() 写一个合适的比较函数,以实现您要实现的排序顺序,名称为sort_compare_func()
  5. run the sort algorithm on sort_array with total_elements using sort_compare_func() 运行排序算法sort_arraytotal_elements使用sort_compare_func()

I'm not sure if your homework requires you to implement your own sort algorithm. 我不确定您的作业是否需要您实现自己的排序算法。 My code fragment will use the standard POSIX function qsort() : 我的代码片段将使用标准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);

Simple test code: 100 elements with random time from 0 to 100: 简单的测试代码: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];
}
...

Some test runs: 一些测试运行:

$ 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

Hope this helps. 希望这可以帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM