指针进阶运用——回调函数
qsort函数的介绍
函数模型
void qsort(void* base, //待排序的数组的起始地址
size_t num, //元素个数
size_t width, //一个元素的大小
int (cmp)(const void e1, const void* e2)//两个元素的比较函数
);
qsort函数一共有四个参数,说明:
(1)void*base;空类型指针——相当中转站——可以存放各种类型的函数;以便用来排序各种类型的数据。注意空类型的指针不能直接使用,需要强制类型的转化。
(2)size_t width 一个元素有几个字节的大小;作用:用来遍历整个数组元素地址;交换元素字节的个数。
(3)比较函数需要依据你想要排序的类型来自己写。e1和e2为比较元素的地址,但前一个数大于第二数返回>0 , 等于返回0 , 小于<0.
(4)qsort函数排序的思想是快速排序。
冒泡排序思想回顾
主要思想:一个数组,相邻的元素两两相互比较,如果前者大,就往下沉;否则,继续往下比较,直到最后一个元素,此为一趟;一趟的比较会最重沉底,最轻的会往上浮以层;最后较大的沉下之后,最轻的元素也就浮到了水面。所以,需要比较n-1趟;每趟比较需要进行n-1-i 次。
void bubble_sort(int arr[], int sz)
{
//趟数
int i = 0;
for (i = 0; i < sz - 1; i++)
{
//一趟冒泡排序的过程
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;
}
}
}
}
以冒泡排序的思想来实现对各种数据类型的排序
思路:注意到qsort函数的思想,设void bubble_sort(void* base, size_t sz, size_t width, int (cmp)(const void e1, const void* e2))参数和qsort函数一样;冒泡排序,趟数和比较次数不需要改变,需要改变的是比较方式和交换方式。通用的交换方式——交换每一个字节的交换。
void swap(char* buf1, char* buf2, int width)
{
int i;
for (i = 0; i < width; i++)
{
char tmp = *(buf1 + i);
*(buf1 + i) = *(buf2 + i);
*(buf2 + i) = tmp;
}
}
void bubble_sort(void* base, size_t sz, size_t width, int (*cmp)(const void* e1, const void* e2))
{
int i, j;
for (i = 0; i < sz - 1; i++)
{
for (j = 0; j < sz - 1 - i; j++)
{
//char*使得地址以一个字节为单位走,配合width可访问整个数组的元素
if(cmp((char *)base + width*j,(char *)base + width*(j+1))>0)
swap((char*)base + width * j, (char*)base + width * (j + 1),width);
//如果条件成立,实先元素交换,传width可以知道交换几个字节数
}
}
}