一、qsort()函数的简介
qsort()函数是C语言库函数的排序函数,既然是排序函数那就有它排序的原理,比如:选择排序、冒泡排序、归并排序、快速排序等。这里qsort()函数底层原理是采用快速排序,下面让我们来了解一下qsort()函数。
由以上图可知:
引头文件:<stdlib.h>
功能:排序无序数组或字符串
参数:
1.base - 指向待排序数组或字符串的指针
2.num - base指针指向数组元素的个数
3.size - 数组中每个元素的大小,以字节为单位
4.compar - 用来比较两个函数的大小(自己定义实现)
返回值:该函数无返回值
二、qsort()函数实例
1.排序整形数组
#define M 10
#include <stdio.h>
#include <stdlib.h>
//整形数据排序
void cmp(const void* e1, const void* e2)
{
return *(int*)e1 - *(int*)e2;
}
int main()
{
int arr[M] = { 1,3,5,7,9,2,6,4,8,10 };
int sz = sizeof arr / sizeof(arr[0]);
printf("排序前 arr[] = [");
for (int i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
printf("]\n");
qsort(arr, sz, sizeof(int), cmp);
printf("排序后 arr[] = [");
for (int i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
printf("]\n");
return 0;
}
结果:
2.排序double型数组
void cmp(const void* e1, const void* e2)
{
return *(double*)e1 > *(double*)e2 ? 1 : -1;
}
int main()
{
double arr[M] = { 1.1,3.2,5.4,7.1,9.6,2.5,6.3,4.8,8.1,10.6 };
/*int sz = sizeof arr / sizeof(arr[0]);*///此时sizeof只能操作整形数据
int sz = M;
printf("排序前 arr[] = [");
for (int i = 0; i < sz; i++)
{
printf("%.1lf ", arr[i]);
}
printf("]\n");
qsort(arr, sz, sizeof(double), cmp);
printf("排序后 arr[] = [");
for (int i = 0; i < sz; i++)
{
printf("%.1lf ", arr[i]);
}
printf("]\n");
return 0;
}
结果:
3.排序字符型数据
//字符型数据排序
void cmp(const void* e1, const void* e2)
{
return *(char*)e1 - *(char*)e2;
}
int main()
{
char str[] = "ahfimcv";
int sz = strlen(str);
printf("排序前:str[] = %s\n",str);
qsort(str, sz, sizeof(str[0]), cmp);
printf("排序后:str[] = %s\n", str);
return 0;
}
结果:
4.结构体类型数据排序
struct Student
{
char name[20];
char num[20];
int age;
};
//按名字首字母进行排序
int cmp_name(const void* e1, const void* e2)
{
//使用trrcmp进行首元素比较
return strcmp(((struct Student*)e1)->name, ((struct Student*)e2)->name);
}
int main()
{
struct Student stu[3] = { {"zhangsan","001",18},{"lisi","002",19},{"wangwu","003",20} };
int sz = sizeof stu / sizeof(stu[0]);
printf("排序前:\n");
for (int i = 0; i < sz; i++)
{
printf("%s %s %d", stu[i].name, stu[i].num, stu[i].age);
printf("\n");
}
qsort(stu, sz, sizeof(stu[0]), cmp_name);
printf("\n排序后:\n");
for (int i = 0; i < sz; i++)
{
printf("%s %s %d", stu[i].name, stu[i].num, stu[i].age);
printf("\n");
}
return 0;
}
结果:
三、使用冒泡排序模拟qsort()函数
Swap()函数:
(1)需要把每个交换的数据在内存中所占的字节数传过去 —— width
(2)因为要交换的数据类型未知,我们采用**一个字节一个字节进行交换**,所以把数据转换为char*较好
my_qsort()函数:
(1)void* base —— 接收待排序数组
(2)num —— 数组元素个数
(3)width —— 每个数据所占的字节数
(4)int(*cmp)(const void* e1, const void* e2) —— 定义一个比较函数,这里是函数指针
int cmp(const void* e1,const void* e2)
{
return *(int*)e1 - *(int*)e2;
}
void Swap(void* buf1, void* buf2, int width)
{
for (int i = 0; i < width; i++)
{
char tmp = *((char*)buf1 + i);
*((char*)buf1 + i) = *((char*)buf2 + i);
*((char*)buf2 + i)= tmp;
}
}
void my_qsort(void* base, int num, int width, int(*cmp)(const void* e1, const void* e2))
{
for (int i = 0; i < num - 1; i++)
{
for (int j = 0; j < num - i - 1; j++)
{
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[10] = { 1,3,4,6,8,10,2,5,7,9 };
printf("排序前:arr[] = [");
int sz = sizeof arr / sizeof(arr[0]);
for (int i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
printf("]\n");
my_qsort(arr, sz, sizeof(arr[0]), cmp);
printf("排序后:arr[] = [");
for (int i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
printf("]\n");
return 0;
}
结果展示: