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

2024-01-15  本文已影响0人  老k的小茅屋

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!

上一篇 下一篇

猜你喜欢

热点阅读