C语言利用回调函数实现qsort函数

1.qsort函数实现排序

qsort函数是无类型比较函数:对任意类型的数据进行排序(整型,浮点型,字符串类型等)

void qsort (void* base, size_t num, size_t size,int (compar)(const void,const void*))

注意:qsort函数中的第四个参数 compar是自己写的

其中:
void* base:待排序数据的起始地址(void也可以看看出是无类型排序)
size_t num:待排序数据的个数
size_t size:待排序数据每个元素的大小 与类型无关
int (compar)(const void,const void
)(函数指针):对待排序的数据进行比较;compar函数需要传入的两个参数为待比较数据的地址

注意

  • qsort函数不关心数据类型,但compar比较函数需要关心数据类型;
  • compar的返回值为int,决定排序算法的升或降,共有三种情况:1、0、-1
    (0表示待比较的数据相等,1表示待比较的数据需要交换位置,大数在后)

1.1 qsort函数实现整形排序

下面以整型数组排序为例
int arr[] = { 3,2,5,7,34,1,342,782,-9,6,32,1 };

#include <stdio.h>
#pragma warning(disable:4996)
#include<Windows.h>
#include<assert.h>
//传入数据加const 因为待比较的两个数据一般中间不会修改
int CompInt(const void *xp, const void *yp)// *xp、*yp是待比较两个元素的地址
{
	// 对参数合法性进行校验
	assert(xp);
	assert(yp);
	// 将待比较的两个元素类型进行强转
	const int *x = (const int*)(xp);
	const int *y = (const int*)(yp);
	if (*x>*y)
	{
		return 1;// 升序  若为-1为降序
	}
	else if (*x < *y)
	{
		return -1;
	}
	else
	{
		return 0;
	}
}
int main()
{
	int arr[] = { 3,2,5,7,34,1,342,782,-9,6,32,1 };
	int num = sizeof(arr) / sizeof(arr[0]);
	qsort(arr, num, sizeof(int), CompInt);
	for (int i = 0; i < num; i++)
	{
		printf("%d ", arr[i]);
	}
}

在这里插入图片描述

1.2qsory实现浮点数排序

3.89,2.7,5.34,7.87,3.4,1.98,34.29,78.2,-9.987,6.797,32.89,1.1

#include <stdio.h>
#pragma warning(disable:4996)
#include<Windows.h>
#include<assert.h>
//传入数据加const 因为待比较的两个数据一般中间不会修改
int CompDouble(const void *xp, const void *yp)// *xp、*yp是待比较两个元素的地址
{
	// 对参数合法性进行校验
	assert(xp);
	assert(yp);
	// 将待比较的两个元素类型进行强转
	const double *x = (const double*)(xp);
	const double *y = (const double*)(yp);
	if (*x>*y)
	{
		return 1;
	}
	else if (*x < *y)
	{
		return -1;
	}
	else
	{
		return 0;
	}
}
int main()
{
	double arr[] = { 3.89,2.7,5.34,7.87,3.4,1.98,34.29,78.2,-9.987,6.797,32.89,1.1 };
	int num = sizeof(arr) / sizeof(arr[0]);
	qsort(arr, num, sizeof(double), CompDouble);
	for (int i = 0; i < num; i++)
	{
		printf("%f\n", arr[i]);
	}
}

在这里插入图片描述

1.3 qsort函数实现对字符串比较

“abcdg12689”
“acasDhxsH76t”

字符串比较规则
从左向右依次比较字符串字符的ASCALL码

例如:
char *arr[] = {
“abcgyd6795”,
“asaA8389”,
“SFsasd9f8”,
“efawekHCSF08”,
“34fa3AFQW”
};

#include <stdio.h>
#pragma warning(disable:4996)
#include<Windows.h>
#include<assert.h>
//传入数据加const 因为待比较的两个数据一般中间不会修改
int CompString(const void *xp, const void *yp)// *xp、*yp是字符指针的地址  void*可以保存二级指针
{
	// 对参数合法性进行校验
	assert(xp);
	assert(yp);
	// 将待比较的两个元素类型进行强转
	const char **x = (const char**)(xp);
	const char **y = (const char**)(yp);
	//定义两个指针指向待比较的两个字符串的起始地址
	//  *x *y表示待比较的两个字符串首地址
	char *_x = *x;
	char *_y = *y;
	while (*_x||*_y) // 字符串元素不为0,即字符串元素没有对比完
	{
		if (*x > *y)
		{
			return 1;
		}
		else if (*x < *y)
		{
			return -1;
		}
		*_x++; *_y++;
	}
	return 0;
}
int main()
{
	// 将多个字符串存放在二维字符数组中
	char *arr[] = {
		"abcgyd6795",
		"asaA8389",
		"SFsasd9f8",
		"efawekHCSF08",
		"34fa3AFQW"
	};
	int num = sizeof(arr) / sizeof(arr[0]);
	qsort(arr, num, sizeof(char *), CompString);// 每个元素类型是一个字符指针
	for (int i = 0; i < num; i++)
	{
		printf("%s\n", arr[i]);
	}
}

在这里插入图片描述字符串比较时也可以直接用字符串比较函数strcmp

#include <stdio.h>
#pragma warning(disable:4996)
#include<Windows.h>
#include<assert.h>
#include<string.h>
//传入数据加const 因为待比较的两个数据一般中间不会修改
int CompString(const void *xp, const void *yp)// *xp、*yp是字符指针的地址  void*可以保存二级指针
{
	// 对参数合法性进行校验
	assert(xp);
	assert(yp);
	// 将待比较的两个元素类型进行强转
	const char **x = (const char**)(xp);
	const char **y = (const char**)(yp);
	return strcmp(*x, *y);
}
int main()
{
	// 将多个字符串存放在二维字符数组中
	char *arr[] = {
		"abcgyd6795",
		"asaA8389",
		"SFsasd9f8",
		"efawekHCSF08",
		"34fa3AFQW"
	};
	int num = sizeof(arr) / sizeof(arr[0]);
	qsort(arr, num, sizeof(char *), CompString);// 每个元素类型是一个字符指针
	for (int i = 0; i < num; i++)
	{
		printf("%s\n", arr[i]);
	}
}

2.利用冒泡排序实现qsort函数

//-----------自己实现qsort函数-------------- 
#include <stdio.h>
#pragma warning(disable:4996)
#include<Windows.h>
#include<assert.h>
#include<string.h>
int CompString(const void *xp, const void *yp)// *xp、*yp是字符指针的地址  void*可以保存二级指针
{
	// 对参数合法性进行校验
	assert(xp);
	assert(yp);
	// 将待比较的两个元素类型进行强转
	const char **x = (const char**)(xp);
	const char **y = (const char**)(yp);
	return strcmp(*x, *y);
}
static void swap(char *x,char *y, size_t num)
{
	while (num)
	{
		char temp = *x;
		*x = *y;
		*y = temp;
		x++, y++;
		num--;
	}
}
// comp是回调函数
int MyQsort(void *base,size_t num, size_t size,int(*comp)(const void*,const void*))// size_t是类型重命名  无符号整性
{
	// 对传入指针的合法性进行校验
	assert(base);
	assert(comp);
	// 下面是将待比较元素进行比较交换
	// 但是这块存在一个问题,就是不知道元素是什么类型,交换的时候应该交换几个字节???
	// 例如 int整型 是4个字节  char 字符型是1个字节
	// 解答:不管是什么类型,每次交换一个字节
	char *p = (char*)base;
	// 冒几轮
	for (int i = 0; i < num-1; i++)
	{
		for (int j = 0; j < num - i-1; j++)
		{
			if (comp(p+j*size,p+(j+1)*size)>0) //比较两个元素
			{
				swap(p + j * size, p + (j + 1)*size,size);// size 个字节
			}
		}
	}
}
int main()
{
	// 将多个字符串存放在二维字符数组中
	char *arr[] = {
		"abcgyd6795",
		"asaA8389",
		"SFsasd9f8",
		"efawekHCSF08",
		"34fa3AFQW"
	};
	int num = sizeof(arr) / sizeof(arr[0]);
	MyQsort(arr, num, sizeof(char *), CompString);// 每个元素类型是一个字符指针
	for (int i = 0; i < num; i++)
	{
		printf("%s\n", arr[i]);
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值