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!
网友评论