美文网首页
【tip】C库函数qsort中比较函数使用方法汇总

【tip】C库函数qsort中比较函数使用方法汇总

作者: papi_k的小茅屋 | 来源:发表于2024-01-15 08:58 被阅读0次

    qsort() 函数——对数组进行快速排序。

    函数声明
    void qsort(void base, size_t nitems, size_t size, int (compar)(const void , const void))

    参数
    base -- 指向要排序的数组的第一个元素的指针。
    nitems -- 由 base 指向的数组中元素的个数。
    size -- 数组中每个元素的大小,以字节为单位。
    compar -- 用来比较两个元素的函数。

    注意
    1.qsort对double型数组不适用,因为Cmp返回值为int型,若两个小数差距极小,例如:a=0.15 ,b=0.14,将会被强制转换为0返回,不发生交换。
    2.如果两个元素的值是相同的,那么它们的前后顺序是不确定的。也就是说qsort()是一个不稳定的排序算法。
    3.当比较两个整数时,如果a和b的取值范围比较大,使用*(char *)a - *(char *)b会出现越界的情况,如a是大正数,b是大负数。这时应该使用大于小于符号来判断。

    比较1:两字符串比较排序

    int Cmp(const void *a ,const void *b)
    {
        return strcmp((char *)a , (char *)b); // a,b是分别要比较的字符串
    }
    

    比较2:对一个字符串中的字符排序

    // 对一个字符串中的字符排序,如“cba”,经过Cmp后就是"abc"
    int Cmp(const void *a, const void *b)
    {
        return *(char *)a - *(char *)b;
    }
    

    比较3:一维整数数组排序

    int Cmp(const void *a, const void *b)
    {
        return *(int *)a - *(int *)b;
    }
    

    比较4:二维字符串指针数组排序1

    // 二维的字符串指针数组形式的,如:char **,可以这样实现排序:
    int Cmp(const void *a ,const void *b)
    {
        return strcmp(*(char **)a , *(char **)b); // a,b是分别要比较的字符串
    }
    

    比较5:二维字符串指针数组排序2

    // 字符串指针数组排序。如char *arr[5] = { "i", "love", "c", "programming", "language" };
    int Cmp(const void *arg1, const void *arg2) {
        char *a = *(char**)arg1; // 数组名本身算一层指针,而里面的内容又是一层指针, *(char**)arg1 取的是常量字符串的地址。
        char *b = *(char**)arg2;
        return strcmp(a, b);
    }
    
    // 拆分理解:qsort将arr理解为指向数组中第一个元素的指针,而第一个元素是指向常量字符串的指针,也就是说它存储的是常量字符串的地址,所以需要char**。
    // 我们要比较的是字符串,所以还需要在char**基础上进行解引用。
    // 接下来使用strcmp对a和b进行比较。(数组名本身算一层指针,而里面的内容又是一层指针,数组存放的是指向字符串的地址)
    

    比较6:二维字符串指针数组排序3

    // 字符串二维数组排序,如char arr[5][16] = { "i", "love", "c", "programming", "language" };
    int Cmp(const void *arg1, const void *arg2) {
        char *a = (char*)arg1;
        char *b = (char*)arg2;
        return strcmp(a, b);
    }
    
    // arr传入qsort函数,qsort函数将arr理解为指向数组第一个元素的指针,arr的第一个元素是arr[0][0],所以参数arg1和arg2指的是指向"a[i][0]"的指针,
    // a[i][0]是字符,就是char,所以arg1和arg2指的是char *。将void*转换为char*,赋予a和b,调用strcmp函数对a和b进行比较。
    

    比较7:结构体数组排序

    // 结构体排序
    typedef struct
    {
        char name[30];   // 学生姓名
        int Chinese;     // 语文成绩
        int Math;        // 数学成绩
        int English;     // 英语成绩
    }st;
    
    int Cmp(const void* a, const void* b)
    {
        st* pa = (st*)a; // 或者 st pa = *(st*)a;
        st* pb = (st*)b; // 或者 st pb = *(st*)b;
        int num1 = pa->Chinese + pa->English + pa->Math;
        int num2 = pb->Chinese + pb->English + pb->Math;
    
        //return (int)num1 - num2;   // 从小到大
        return (int)num2 - num1;   //  从大到小
    }
    

    比较8:整型二维数组排序1

    // 注意这种适合输入的数组是int **方式,而不是int [m][n]的方式。
    int Cmp(const void *a, const *b)
    {
        // 转换为对应的一维数组
        int *array1 = *(int **)a; // 用这个不行(int *)a;
        int *array2 = *(int **)b; // 用这个不行(int *)b;
        //获取对应array1的两个元素
        int x1 = array1[0]; // 验证将 *array1 替换为array1[0], 可以通过。
        int y1 = array1[1]; // 验证将 *(array1 + 1) 可替换为array1[1]。
        //获取对应array2的两个元素
        int x2 = array2[0];
        int y2 = array2[1];
        return (x1 * x1 + y1 * y1) - (x2 * x2 + y2 * y2);
    }
    

    比较9:整型二维数组排序2

    // 注意这种适合输入的数组是int [m][n]方式,而不是int **的方式。
    int Cmp(const void *a, const void *b)
    {
        int *t1 = (int *)a; // 使用*(int **)a方式无效。
        int *t2 = (int *)b; // 使用*(int **)b方式无效。
        return t1[0] - t2[0];
    }
    

    参考学习链接:
    C 库函数 - qsort()


    yo peace!

    相关文章

      网友评论

          本文标题:【tip】C库函数qsort中比较函数使用方法汇总

          本文链接:https://www.haomeiwen.com/subject/ssrcodtx.html