Sorting an array using multiple sort criteria (QuickSort)

前端 未结 5 1623
傲寒
傲寒 2020-12-21 05:09

I am trying to find out how (using a quicksort algorithm) to sort an struct array by 2 criterias. For example say I had a struct of:

struct employee{
   char         


        
相关标签:
5条回答
  • 2020-12-21 05:44

    I think you should sort your array by gender first, one for male, one for female. Then use the quicksort function to sort within those two arrays.

    You can use strcmp to sort the original array into two arrays: one for male, one for female.

    0 讨论(0)
  • 2020-12-21 05:46

    Just use the built-in qsort, and pass it a comparator function that compares gender first, and consults ID number only in case of "ties" in the first comparison.

    0 讨论(0)
  • 2020-12-21 05:48

    It's not hard. You just need a function (or block of code seeing you want it "hard coded") to compare your structs. In the sample code you've given you are comparing the current object using arr[l].id <= arr[p].id. That is you are only considering id to work out where your element fits. You just need to compare using the other fields at this point. It would be much tidier with a function (I gave you such a function in your earlier question).

    You are also only shifting the id fields when you swap - leaving the name and gender unchanged in your data items. You should move the whole struct.

    0 讨论(0)
  • 2020-12-21 05:49
    int compare_employee (struct employee * a, struct employee * b) {
        int diff = strcmp(a->gender, b->gender);
    
        if (diff) // if gender different
            return -diff; // sort descending, please double check this and reverse in case I am wrong
    
        return a->id - b->id; // else sort by id
    }
    

    Will output a negative number if a < b, positive if a > b, zero if they are equal.

    Use it eigther in your own quicksort or as a qsort comparator.

    0 讨论(0)
  • 2020-12-21 06:01

    You can certainly inline the comparison function, and a swapper for that matter. This code below is pretty basic and relies on valid pointers, but you'l get the idea. I also took the liberty of trimming down your quicksort, fixing what was off along the way (I hope).

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    // employee record
    struct employee
    {
        char gender[12];
        char name[12];
        int id;
    };
    
    // swap employee records
    void swap_employee(struct employee *left, struct employee *right)
    {
        struct employee tmp = *right;
        *right = *left;
        *left = tmp;
    }
    
    // compare employee records
    int compare_employee(const struct employee* left,
                         const struct employee* right)
    {
        int gender = strcmp(left->gender, right->gender);
        return (gender ? gender : (left->id - right->id));
    }
    
    // quicksort for employees
    static void quicksort_(struct employee *arr, int left, int right)
    {
        struct employee p = arr[(left+right)/2];    // as good as any
        int l = left, r = right;   // movable indicies
    
        while (l <= r)
        {
            while (compare_employee(arr+l, &p) < 0)
                ++l;
            while (compare_employee(arr+r, &p) > 0)
                --r;
            if (l <= r)
            {
                swap_employee(arr+l, arr+r);
                ++l; --r;
            }
        }
    
        if (left < r)
            quicksort_(arr, left, r);
        if (l < right)
            quicksort_(arr, l, right);
    }
    
    // exposed API
    void quicksort(struct employee *arr, int count)
    {
        if (arr && (count>0))
            quicksort_(arr, 0, count-1);
    }
    
    /* sample usage */
    int main(int argc, char *argv[])
    {
        struct employee arr[]=
        {
            {"male","Matt",1234},
            {"female","Jessica",2345},
            {"male","Josh",1235},
            {"female","Betsy",2344},
            {"male","Roger",1233}
        };
    
        quicksort(arr, sizeof(arr)/sizeof(arr[0]));
    
        for (int i=0;i<sizeof(arr)/sizeof(arr[0]);++i)
            printf("%s, %s, %d\n", arr[i].gender,arr[i].name, arr[i].id);
    
        return EXIT_SUCCESS;
    }
    

    Results

    female, Betsy, 2344
    female, Jessica, 2345
    male, Roger, 1233
    male, Matt, 1234
    male, Josh, 1235
    
    0 讨论(0)
提交回复
热议问题