【C语言】指针篇-精通库中的快速排序算法:巧妙掌握技巧(4/5)

请添加图片描述
请添加图片描述

Alt

🌈个人主页:是店小二呀
🌈C语言笔记专栏:C语言笔记
🌈C++笔记专栏: C++笔记

🌈喜欢的诗句:无人扶我青云志 我自踏雪至山巅
请添加图片描述


一、回调函数

回调函数通过一个函数指针调用的函数。把一个函数的地址作为一个参数传递给另外一个函数,当这个地址被用来调用其指向的函数时,被调用函数称为回调函数(跟函数嵌套差不多

//使⽤回到函数改造后
#include <stdio.h>
int add(int a, int b)
{
	return a + b;
}
int sub(int a, int b)
{
	return a - b;
}
int mul(int a, int b)
{
	return a * b;
}

int d(int a, int b)
{
	return a / b;
}

void calc(int(*pf)(int, int))
{
	int ret = 0;
	int x, y;
	printf("输⼊操作数:");
	scanf("%d %d", &x, &y);
	ret = pf(x, y);
	printf("ret = %d\n", ret);
}

int main()
{
	int input = 1;
	do
	{
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			calc(add);
			break;
		case 2:
			calc(sub);
			break;
		case 3:
			calc(mul);
			break;
		case 4:
			calc(d);
			break;
		case 0:
			printf("退出程序\n");
			break;
		default:
			printf("选择错误\n");
			break;
		}
	} while (input);
	return 0;
}

二、快速排序(Qsort)

快速排序属于九大排序之一,并且该函数在头文件stdlib.h 声明
请添加图片描述

2.1 Qsort参数部分介绍

void qsoer(void *base, size_t num, size_t size, int (*compare)(const void*,const void*))
  • void * base:待排序数据的起始位置,第一个元素
  • size_t num:待排序数据的元素个数
  • size_t size:待排序数据的每个元素的大小,单位是字节
  • int (*compare)(const void *,const void *):函数指针-指针指向的函数是来比较待排序数据中的两个元素大小关系

注意】:void 是无具体类型的指针(通用指针类型),对此可以接收任意数据类型的地址

2.2 不同类型的比较方法

提前说明】:关于比较函数的参数部分,void *是无具体类型的指针(通用指针类型),对此可以接收任意数据类型的地址。

整形类型:

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

字符类型(比较单字符的大小,字符串函数头文件string.h):

int char_compare(const void* e1, const void* e2)
{
	return strcmp((char*)e1, (char*)e2);
} 

字符串长度

int charnums_compare(const void* e1, const void* e2)
{
	return strlen((char*) e1) - strlen((char*) e1);
}

结构体整形成员

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

结构体字符串成员

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

说明】:不同类型数据的比较不能单单只通过大于小于号去判断,需要掌握不同类型的比较方法,以便于更好的使用qsort函数,但是在C++中,一般使用sort,而不是qsort函数,因为使用起来很复杂,而且需要自己实现个比较函数。

2.3 简单使用Qsort(对任意数据类型进行排序)

struct su
{
    int age;
    char name[100];
};
int main()
{
    int nums[] = { 2,6,7,9,10,1,8,5,3 };
    int sz = sizeof(nums) / sizeof(nums[0]);
    qsort(nums, sz, sizeof(nums[0]), compare);//函数名变身就是一个函数指针变量
    
    //结构体数组
    struct su s[] = { {18,"zhangsana"},{14,"xiaoming"},{9,"lierdan"} };
    int sz2 = sizeof(s) / sizeof(s[0]);
    qsort(s, sz, sizeof(s[0]), age_compare);
    return 0;

}

三、冒泡排序思想模拟实现快速排序(不是真正的快速排序)

前文:冒泡排序是一种简单的排序,但是只能排序整形数据,无法适应不同类型的场景。对此,我们将通过冒泡排序的思想模拟实现一个对任意类型能排序的快速排序

注意】:快速排序的底层不是这样子实现的,对此这里不是真正的快速排序

int main()
{
	int nums[] = { 2,6,7,9,10,1,8,5,3 };
	int sz = sizeof(nums) / sizeof(nums[0]);
	int with = sizeof(nums[0]);
	my_qsort(nums, sz, with, int_compare);
    return
}

3.1 函数内部:

void my_qsort(int* p, int sz, int width, int (*compare)(const void* e1, const void* e2))
{
	for (int i = 0; i < sz - 1; i++)
	{
		for (int j = 0; j < sz - i - 1; j++)
		{		
			if(compare((char*)base+j*width,(char *)base+(j+1)*width)>0)//compare 根据类型去定义
			{ 
				Swap((char*)base + j * width, (char*)base + (j + 1) * width, width);
			}
		}
	}
}

【说明】:函数实现框架跟冒泡排序相似,主要的不同在于判断和交换语句底层逻辑的不同


3.2 底层逻辑解析

3.2.1 判断语句:

if(compare((char*)base+j*width,(char *)base+(j+1)*width))

说明】:

强制类型转化为char*类型(char *类型对于±整形,偏移量为一个字节)。width是某个类型的大小,那么这两个参数之间相差width大小,正好跳过某个类型元素。(适用于任意的数据进行比较)

3.2.2 比较函数:

int int_compare(const void* e1, const void* e2)//对比分类型
{
	return *(int*)e1 - *(int*)e2;
}

函数名】:int_compare表明了这里适合对整形数据对比,对于不同数据类型有不同的比较方法,在上面使用库函数qsort中有所涉及

3.2.3 Swap函数参数:

Swap((char*)base + j * width, (char*)base + (j + 1) * width, width)

说明】:base是待排序数据的起始位置(首元素的地址),强制类型转化为char*类型,使得对于±整型,偏移量为一个字节。width是某个类型的大小,那么这两个参数之间相差width大小,正好跳过某个类型元素(j * width(j + 1) * width )。(适用于任意的数据进行比较)

3.2.4 Swap内部逻辑:

void Swap(char* e1, char* e2,int width)
{
	for (int i = 0; i<width;i++)
	{
		char tmp = *e1;
		*e1 = *e2;
		*e2 = tmp;
		e1++;
		e2++;
	  }
}

说明】:强制类型转化为char *的目的是对于两个参数部分,逐一字节交换e1/2++不断向后移动到新的位置,再进行交换。Swap只交换一次,交换的字节数到达某类型的大小,则完成交换。(适用于任意的数据进行交换)


请添加图片描述

以上就是本篇文章的所有内容,在此感谢大家的观看!这里是店小二C语言笔记,希望对你在学习C语言中有所帮助!

  • 127
    点赞
  • 73
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 94
    评论
C语言是一种广泛应用于系统编程和嵌入式开发的高级编程语言。函数指针是C语言的一个重要概念,它可以指向函数,并且可以通过函数指针来调用函数。快速排序算法是一种常用的排序算法,它的核心思想是通过分治的策略将一个大问题分解为多个小问题,并通过递归的方式解决这些小问题。 下面是C语言使用函数指针实现快速排序算法的示例代码: ```c #include <stdio.h> // 交换两个元素的值 void swap(int* a, int* b) { int temp = *a; *a = *b; *b = temp; } // 快速排序的分区函数 int partition(int arr[], int low, int high) { int pivot = arr[high]; // 选取最后一个元素作为基准 int i = (low - 1); // 定义一个指针,用于指向小于基准的元素 for (int j = low; j <= high - 1; j++) { if (arr[j] < pivot) { i++; swap(&arr[i], &arr[j]); } } swap(&arr[i + 1], &arr[high]); return (i + 1); } // 快速排序函数 void quickSort(int arr[], int low, int high) { if (low < high) { int pi = partition(arr, low, high); // 将数组分区,并获取分区点的位置 quickSort(arr, low, pi - 1); // 对分区点左边的子数组进行快速排序 quickSort(arr, pi + 1, high); // 对分区点右边的子数组进行快速排序 } } // 打印数组元素 void printArray(int arr[], int size) { for (int i = 0; i < size; i++) { printf("%d ", arr[i]); } printf("\n"); } int main() { int arr[] = {10, 7, 8, 9, 1, 5}; int n = sizeof(arr) / sizeof(arr[0]); printf("原始数组:"); printArray(arr, n); quickSort(arr, 0, n - 1); printf("排序后的数组:"); printArray(arr, n); return 0; } ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

是店小二呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值