学习之前 首先我们来看一下C语言标准库给出的定义
qsort函数的头文件是<stdlib.h>
Sort elements of array 表示qsort的功能是排序数组的元素,不难发现它的返回类型为void 接下来我们来仔细分析下它的四个参数:
第一个参数是指针base,指向要被排序的数组中第一个元素,也就是数组名。 类型为void*
第二个参数为num,表示排序的数组中的元素个数, 类型是sizt_t
第三个参数是size,表示排序数组中一个元素的字节大小,类型同样是size_t
前三个参数不用过多解释,最后一个参数我们重点讲解一下!
最后一个参数compar:是使用者传过来的一个函数指针指向用来比较两个元素的函数 这个函数被qsort反复调用以比较两个元素。应遵循以下原型:
Int (const void* p1, const void* p2); 函数参数为两个void*类型的指针p1和p2
这里需要注意void*类型的指针不能直接解引用,需要强制类型转换为对应的类型在解引用!
函数返回类型为int,通过函数的返回值来对数组元素进行排序。根据返回值有下列排序情况
<0 p1所指向的元素在p2所指向的元素之前 =0 p1指向的元素和p2指向的元素是等价的 >0 p所指向的元素在p2所指向的元素之后
int 类型:
int int_cmp(const void* p1, const void* p2)
{
return (*(int*)p1 - *(int*)p2);
}
char类型:
int char_cmp(const void* p1, const void* p2)
{
return (*( char*)p1 - *(char*)p2);
}
double类型:注意由于double类型的精度有限,这里我们使用三目操作符直接判断
int double_cmp(const void* p1, const void* p2)
{
return (*(double*)p1 > *(double*)p2 ? 1 : -1);
}
结构体类型:
//我们声明一个结构体
struct Stu //学生
{
char name[20];//名字
int age;//年龄
char id[20]//学号
};
//假设按照年龄来排序
int cmp_stu_by_age(const void* p1, const void* p2)
{
return ((struct Stu*)p1)->age - ((struct Stu*)p2)->age;
}
//假设按照名字排序
int cmp_stu_by_name(const void* p1, const void* p2)
{
return strcmp(((struct Stu*)p1)->name, ((struct Stu*)p2)->name);//strcmp用来比较两个字符串大小
}
//按照学号排序
int cmp_stu_by_id(const void* p1, const void* p2)
{
return strcmp(((struct Stu*)p1)->id, ((struct Stu*)p2)->id);
}
下面我们来简单使用一下qsort 排序一个整形数组进行升序排序
代码如下:
#include <stdio.h>
#include<stdlib.h>
//qosrt函数的使用者需要自己实现一个比较函数
int int_cmp(const void* p1, const void* p2)
{
return (*(int*)p1 - *(int*)p2);//这里我们要求排序为升序
}
int main()
{
//利用qsort对下面这个无序整形数组排序
int arr[] = { 1, 3, 5, 7, 9, 2, 4, 6, 8, 0 };
int i = 0;
//调用qsort
qsort(arr, sizeof(arr) / sizeof(arr[0]), sizeof(int), int_cmp);
for (i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
{
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
代码运行结果如下:
我们再来看一组char类型数据的排序:
#include <stdio.h>
#include <stdlib.h>
int char_cmp(const void* p1, const void* p2)
{
return *(char*)p1 - *(char*)p2; //要求升序
}
int main()
{
char arr[] = { 'f', 'b','e','a','d','c' };
int sz = sizeof(arr) / sizeof(arr[0]);
qsort(arr, sz, sizeof(arr[0]), char_cmp);
for (int i = 0; i < sz; i++)
{
printf("%c ", arr[i]);
}
return 0;
}
对double类型数据进行qsort排序:
int double_cmp(const void* p1, const void* p2)
{
return (*(double*)p1 > *(double*)p2 ? 1 : -1);
}
void test02()
{
double arr[] = { 3.14,2.6,2.3,1.7 };
int sz = sizeof(arr) / sizeof(arr[0]);
qsort(arr, sz, sizeof(arr[0]), double_cmp);
for (int i = 0; i < sz; i++)
{
printf("%lf ", arr[i]);
}
}
int main()
{
test02();
return 0;
}
排序结果:
我们在使用qsort对结构体类型数据排序一次代码如下:
struct Stu //学⽣
{
char name[20];//名字
int age;//年龄
};
int cmp_stu_by_name(const void* p1, const void* p2)
{
return strcmp(((struct Stu*)p1)->name, ((struct Stu*)p2)->name);//我们要求升序排序
}
void test0()
{
struct Stu s[] = { {"zhangsan", 20}, {"lisi", 30}, {"wangwu", 15} };
int sz = sizeof(s) / sizeof(s[0]);
qsort(s, sz, sizeof(s[0]), cmp_stu_by_name);
//我们观察下排序后的排列情况
for (int i = 0; i < sz; i++)
{
printf("%s,%d ", s[i].name, s[i].age);
}
}
int main()
{
test0();
return 0;
}
程序运行结果如下:
上代码!
//模拟qsort编写一个函数实现对各种数据的冒泡排序
int comp_t(const void* p1, const void* p2)
{
return *(int*)p1 - *(int*)p2;
}
void Swap(void* p1, void* p2, int size)
{
int i = 0;
for (i = 0; i < size; i++)
{
char tmp = *((char*)p1 + i);
*((char*)p1 + i) = *((char*)p2 + i);
*((char*)p2 + i) = tmp;
}
}
void my_bubble_sort(void* base, size_t sz, size_t width, int (*cmp)(const void* p1, const void* p2))
{
//趟数
int i = 0;
for (i = 0; i < sz - 1; i++)
{
//一趟内部的两两比较
int j = 0;
for (j = 0; j < sz - 1 - i; j++)
{
//比较arr[j] 和 arr[j + 1]
if (cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0)//改变
{
//交换两个元素
Swap((char*)base + j * width, (char*)base + (j + 1) * width, width);
}
}
}
}
int main()
{
int arr[] = { 1,4,7,2,5,0,8,9,6,3 };
int i = 0;
my_bubble_sort(arr, sizeof(arr) / sizeof(arr[0]), sizeof(int), comp_t);
for (i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
{
printf("%d ", arr[i]);
}
return 0;
}
冒泡排序结果如上!
好了到此为止我们所有关于qsort函数的讲解就结束了,那么本期内容就到这里,如果对你有帮助记得一键三连,如果有不足的地方欢迎各位大佬指正!更多精彩内容敬请期待!