文章目录
1.快速上手qsort()函数
1.1基本信息
-
qsort()函数是
stdlib.h
中的库函数,通过“快速排序”算法实现对数组的排序。1.2 函数定义
void qsort(void *base,size_t nmemb,size_t size, int (*compar)(const void *,const void *));
-
base
传入需要排序的数组的首地址
-
nmemb
传入需要排序的数组的元素 -
size
待排序数组中一个元素所占据的内存大小 -
compar
一个自定义的函数,将决定升序排列还是降序排列。这也是实现对不同类型数据排序的关键。【函数定义中是传入一个函数指针,不熟悉的朋友可以查查相关文章:指针的进阶使用】
1.3 compar(const void*,const void*)
根据qsort()的函数定义,我们需要按需完成compar函数的定义。该函数要求传入两个数据的地址,将他们比较后返回一个整型值。由于函数的参数是两个void类型的指针,我们需要强制类型转换为整型类型的指针,解引用后再将两个值作差,便能比较出两个数据的大小。
这样的自定义函数可以给用户很大的操作空间:
-
相当于将所有数据都转化整型进行操作,实现了对不同数据的排序
-
排序字符串时,还可以使用
string.h
中的strcmp()函数直接比较两个字符串,因为其返回值也是整型值
1.4 样例
-
#include<stdio.h>
//自定义比较两个int类型数据的compar函数
//实现升序排列
int comp_int(const void* a, const void* b){
return *(int*)a-*(int*)b;
}
int main(){
int array1[5] = { 9,8,7,6,5 };
int size1 = sizeof(array1) / sizeof(array1[0]);
qsort(array1,size1,sizeof(array1[0]),camp_int);
int i;
for(i=0;i<5;i++)
printf("%d ", array1[i]);
return 0;s
}
2.复刻qsort()函数
2.1实现原理
c语言中的指针,通过地址访问,间接对数据进行操作。不同类型的指针,本质上是在遍历内存时跳过的字节数不同。
例如,32位、64位编译器中,int类型的数据占4字节;float类型的数据占4字节;char类型的数据占1字节。对应的指针在遍历内存时,没加1,跳过的字节数分别是:4字节,4字节,1字节。
为了统一对不同类型值的访问,我们可以使用char类型的指针,模仿其他类型的值的指针对数据的访问。这也是为什么需要向qsort函数传入nmeber
size
两个参数的原因,nmeber
相当于划定了指针操作的最大范围,size
则规定了指针操作的步长。因此,无论什么类型的数据,只要存储在内存中,我们都可以使用相同方法取得其值,然后对它们进行排序,从而实现包括结构体在内的复杂数据类型的排序。
2.2代码
2.2.1 整型指针实现冒泡排序
void BubbleSort(int* num,int size)
{
int i,j;
for(i=0;i<size-1;i++){
for(j=0;j<size-1-i;j++){
if(num[j]>num[j+1]){
int temp=num[j];
num[j]=num[j+1];
num[j+1]=temp;
}
}
}
}
2.2.2 复刻qsort()函数
void BubbleSort_Plus(void* base, int num, int size_unit, int(*cap)(const void*, const void*))
{
int i, j;
for (i = 0; i < num - 1; i++) {
for (j = 0; j < num-1-i; j++) {
if (cap((char*)base+j*size_unit,(char*) base+(j+1)*size_unit)>0) {
change((char*)base + j * size_unit,(char*)base + (j + 1) * size_unit, size_unit);
}
}
}
}
void change(void* a, void* b, int size_unit)
{
int i;
for (i = 0; i < size_unit; i++) {
char temp = *((char*)a+i);
*((char*)a + i) = *((char*)b + i);
*((char*)b + i) = temp;
}
}