序
本次在学习c语言的时候,学到冒泡排序,但是这只能对整型的数据类型排序,没有办法对字符型或者结构型数据类型进行排序,因此这里扩展一个通用的冒泡排序法
这里先看原来冒泡排序的方法,不做过多介绍,可以先复习一下
void bubble_sort(int arr[], int sz)
{
int i = 0;
//趟数
for (i = 0; i < sz-1; i++)
{
int flag = 1;//假设数组是排好序的
int j = 0;
for (j = 0; j < sz - 1 - i; j++)
{
if (arr[j] > arr[j + 1])
{
int tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
flag = 0;
}
}
if (flag == 1)//如果已经是排好序的,那么flag等于1,无须再进行后面的排序
{
break;
}
}
}
int main()
{
int arr[] = { 9,8,7,6,5,4,3,2,1,0};
//数组排成升序
int sz = sizeof(arr) / sizeof(arr[0]);
bubble_sort(arr, sz);
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%d", arr[i]);
}
return 0;
}
接着我们要学习一个新的函数-------qsort函数
qsort函数
msdn解释如下:
void qsort( void *base, size_t num, size_t width, int (__cdecl *compare )(const void *elem1, const void *elem2 ) );
qsort使用的是快速排序思想实现的排序函数,是c语言本身提供的函数,参数__cdecl *compare是函数调用约定,这里不做多介绍,const void* e1,const void*e2是函数指针,void* base是排序的起始位置,num是待排序的数据元素的个数,width是待排序的数据元素的大小,单位为字节。
这个函数可以排序任意类型的数据类型,我们回来看最初冒泡排序的算法,我们知道现在这个冒泡排序不完美在于他只能排序整型类型,因此我们需要改变的是参数的类型,还有两个元素间的比较,但是这里也有一个问题------不同的数据类型排序方法不同
所以qsort函数将不同类型数比较方法提取出来,就是参数中int (*cmp)(const void *elem1, const void *elem2 ) )这个函数指针,这个比较方法由我们定义,相当于回调函数
qsort返回值:
-
Return Value Description < 0 elem1 less than elem2 0 elem1 equivalent to elem2 > 0 elem1 greater than elem2
qsort函数排序整型
因此我们可以写出代码(这里以整型类型比较为例):
cmp_int(const void* e1, const void* e2)
{
if (*e1 > *e2)
return 0;
else if (*e1 == *e2)
return 0;
else
return -1;
}
这里返回0,1,-1好让qsort知道我们比较整型的大小结果
好像明白了,但是还是有个问题,就是我们设立函数去比较时候,肯定调用void*的函数(void*是无具体类型的指针,可以接收任意类型的地址,所以不能解引用,也不能+-整数)但是我们没办法将void*指针解引用呀,所以我们要将void*强制类型转换
修改如下:
cmp_int(const void* e1, const void* e2)
{
if (*(int*)e1 > *(int*)e2)
return 0;
else if (*(int*)e1 == *(int*)e2)
return 0;
else
return -1;
}
但是这样语句比较啰嗦,我们可以用相减的方法去判断结果正负:
//比较两个整型元素
//e1指向一个整数
//e2指向另一个整型
int cmp_int(const void* e1, const void* e2)
{
return (*(int*)e1 - *(int*)e2);
}
int main()
{
int arr[] = { 9,8,7,6,5,4,3,2,1,0};
//数组排成升序
int sz = sizeof(arr) / sizeof(arr[0]);
/*bubble_sort(arr, sz);*/
qsort(arr, sz, sizeof(arr[0]), cmp_int);
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%d", arr[i]);
}
return 0;
}
如果要想改变为降序,只需要改为return (*(int*)e2 - *(int*)e1);就可以了
qsort排序结构体类型
直接上代码,详细解释注释已标:
struct Stu
{
char name[20];
int age;
};
int cmp_stu_by_name(const void* e1,const void* e2)
{
//strcmp返回的值恰好为>0,<0,=0
//这里比较名字,为字符串,因此需要strcmp函数来比较,strcut Stu*为强制类型转换
return strcmp(((struct Stu*)e1)->name, ((struct Stu*)e2)->name);
}
//测试使用qsort来排序结构数据
void test1()
{
struct Stu s[] = { {"zhangsan",15},{"lisi",30},{"wangwu",25} };
int sz = sizeof(s) / sizeof(s[0]);
qsort(s, sz, sizeof(s[0]), cmp_stu_by_name);
}
注意:strcmp比较是一个字符一个字符的比较,比如a>b,b>c