C语言--回调函数实列 模拟qsort函数

qsort函数简介

  • qsort函数包含在C 标准库 - <stdlib.h>中

qsort 的函数原型是:
void qsort(voidbase,size_t num,size_t width,int(__cdeclcompare)(const void*,const void*))

  • void*base为要排序的数组名(地址)
  • size_t num为元素个数
  • size_t width为每个元素所占空间大小,字节数
  • int(__cdecl*compare)(const void*,const void*)为库函数作者提供给使用者自己编写的一个比较函数返回值为int
    如果compar返回值小于0(< 0),那么p1所指向元素会被排在p2所指向元素的左面;
    如果compar返回值等于0(= 0),那么p1所指向元素与p2所指向元素的顺序不确定;
    如果compar返回值大于0(> 0),那么p1所指向元素会被排在p2所指向元素的右面。

__cdecl 是C Declaration的缩写(declaration,声明),表示C语言默认的函数调用方法:所有参数从右到左依次入栈,这些参数由调用者清除,称为手动清栈。被调用函数不会要求调用者传递多少参数,调用者传递过多或者过少的参数,甚至完全不同的参数都不会产生编译阶段的错误。

例主函数代码

struct Stu
{
	char name[20];
	int age;
};
int main()
{
	int arr[10]={1,4,2,5,3,6,9,7,8,10};
	char arr1[10]="ABCEGDF";
	struct Stu s[3] = { {"zhangsan", 30},{"lisi", 34},{"wangwu", 20} };
	int sz=sizeof(s)/sizeof(s[0]);
	qsort(arr1,sz,sizeof(s[0]),cmp_char);
	// for(int i=0;i<sz;i++)
	// {
	// 		printf("%d ",arr[i]);
	// }
	printf("%s\n", arr1);
	
	return 0;
}

compare函数

int类型比较


int cmp_int(const void*e1,const void*e2)
{
	return *(int*)e1-*(int*)e2;
}

char类型比较

int cmp_char(const void*e1,const void*e2)
{
	return *(char*)e1-*(char*)e2;
	//return strcmp((char*)e1,(char*)e2);
}

double类型比较
注意:在对浮点或者double型的一定要用三目运算符,因为要是使用像整型那样相减的话,如果是两个很接近的数则可能返回一个很小的小数(大于-1,小于1),而cmp的返回值是int型,因此会将这个小数返回0,系统认为是相等,失去了本来存在的大小关系(转载)

int cmp_char(const void*e1,const void*e2)
{
	return *(char*)e1 > *(char*)e2 ? 1 : -1;
}

按结构体年龄(int)

int sort_by_age(const void* e1, const void* e2)
{
	return ((struct Stu*)e1)->age - ((struct Stu*)e2)->age;
}

按结构体名字(字符串)

int sort_by_name(const void*e1, const void*e2)
{
	return strcmp(((struct Stu*)e1)->name, ((struct Stu*)e2)->name);
}

自己模拟实现qsort函数

模拟实现冒泡qsort函数

void bubble_qsort(void* base, 
					int sz, 
					int width ,
					int (*cmp)(const void*e1, const void*e2)
					)
{
	for (int i = 0; i < sz-1; ++i)//趟数
	{
		for (int j = 0; j < sz-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);
				//转换类型为char* 方便与width结合使用 第j和第j+1个调换
			}
		}
	}
}

交换函数

void swap(char*buffer1,char*bufffer2,int width)
{
	for(int i=0;i<width;i++)//由于是char* width限制按字节交换
	{
		char tmp=*buffer1;
		*buffer1=*bufffer2;
		*bufffer2=tmp;
		buffer1++;
		bufffer2++;
	}
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值