简体   繁体   中英

Array of pointers that point to structures

My structure is this:

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

And structures of this type are saved in a array of linked lists:

typedef celltype **Hash;

and two structures X and Y are linked into the same list if, for some given function h(char x[]), h(X->name)=h(Y->name) . What I'm trying to say is that these structures are sorted into the array by their 'names'.

Now, I have to sort the structures by their 'time' using array of pointers such that the first pointer in the array points to the structure with the smallest time, the second pointer to the second smallest etc.

How do I do that? I'm still not very good with pointers so I don't know how to approach this at all. I tried looking at the similar questions already posted here but the pointers completely baffle me and I can't seem to make them work for my code.

For example, if I have a function:

void sort(Hash A, celltype *PArray[MAX]){
}

where *PArray[MAX] is my array of pointers and Hash A is where the structures are stored. How do I write the rest of function? How to make a pointer point to a structure??

If you are still stuck, the overview of what you will need to do is iterate over your hash table (ie over each bucket and then over each node of the list contained in each bucket to make your array of pointers point to each entry in your hash table. It doesn't matter how you hash table is keyed, all you care about is making each used pointer in PArray point to a celltype .

I presume you know how to iterate over your hash table. Just loop from 0 to ht_size (where htsize is the number of buckets, eg array elements, in your hash table). You then simply declare a celltype *p pointer and iterate the list pointed to by the bucket entry (which can just be a single celltype* where the next pointer is NULL , or it could be any number based on the hash collision that resulted in more than one celltype* resolving to the bucket hashtable[x] )

Once you have filled PArray so that some number of pointers nptr now point to a celltype* in your hash table, all that remains is calling qsort to sort the pointers by the celltype->time member. The only trick is you must write the compare function to compare the adjacent celltype->time values.

The qsort compare function has the prototype:

int compare (const void *ap, const void *bp);

(where a and b are pointers to adjacent elements being compared. I added the p just to denote them as pointers)

What are we sorting? An array of pointers to celltype . So each member of the array is already a pointer, and if each parameter is a pointer to your adjacent elements, then each parameter will represent a pointer to pointer to celltype .

Once you have worked out what your compare pointers represent, it is just a matter of dereferencing the parameters to allow you to access the time member within each struct. When each parameter is a pointer to pointer , you can cast the parameter to type * const * and dereference to provide you with a pointer to type that you can use to compare the time values, eg

/* qsort compare for array of pointers to celltype */
int compare (const void *ap, const void *bp)
{
    celltype *a = *((celltype * const *)ap);
    celltype *b = *((celltype * const *)bp);

    return (a->time > b->time) - (a->time < b->time);
}

(for any numeric type, returning the result of the two conditionals (a > b) - (a < b) for an ascending sort, simply avoids potential overflow that could result if you return a - b , eg where a could be a large negative value and b a large positive value resulting in overflow)

While you don't show how A is declared, you do show the typedef for Hash that when dereferenced would result in a pointer to celltype . Using ht_size to represent the number of buckets in your hash table, your sort function would then look something like:

void sort(Hash A, celltype *PArray[MAX]){

    size_t nptr = 0;

    for (size_t i = 0; i < ht_size; i++) {  /* loop over buckets */
        celltype *p = A[i];                 /* pointer to celltype */
        while (p) {                         /* iterate over all chained nodes */
            PArray[nptr++] = p;             /* assigning pointer to PArray */
            p = p->next
        }
    }

    qsort (PArray, ntpr, sizeof *PArray, compare);   /* call qsort */
}

That's it in a nutshell. If your still having trouble wrapping your head around the qsort concept in the partial example above, a short full example should remove the confusion, eg

#include <stdio.h>
#include <stdlib.h>

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

int compare (const void *ap, const void *bp)
{
    celltype *a = *((celltype * const *)ap);
    celltype *b = *((celltype * const *)bp);

    return (a->time > b->time) - (a->time < b->time);
}

int main (void) {

    celltype    c1 = { .name = "three", .time = 127.21 },
                c2 = { .name = "one", .time = 127.1 },
                c3 = { .name = "two", .time = 127.19 },
            *pc[] = { &c1, &c2, &c3 };
    size_t n = sizeof pc / sizeof *pc;

    qsort (pc, n, sizeof *pc, compare);

    for (size_t i = 0; i < n; i++)
        printf ("%-5s  %6.2f\n", pc[i]->name, pc[i]->time);
}

Example Use/Output

$ ./bin/qsort_ptp_struct
one    127.10
two    127.19
three  127.21

Look things over and let me know if you have further questions.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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