关于qsort

这篇博客介绍了如何使用C语言中的qsort函数对整型、浮点型和字符型数据进行快速排序。通过示例代码展示了如何自定义比较函数cmp_int、cmp_char和cmp_float。此外,还探讨了如何将冒泡排序扩展以适应更多类型数据的排序,通过bubble_sort函数实现了对整型数组的冒泡排序。
摘要由CSDN通过智能技术生成

如何对整型/浮点型/字符串/结构体等多种类型实现快速排序呢?不得不提到的一个库函数:qsort!

我们先来初步了解一下qsort:

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

qsort库函数包含四个参数。

①第一个参数void*base 也就是需要进行比较的字符串的首元素的地址。由于地址在内存中是连续存放的。得到了首元素的地址就可以顺藤摸瓜找到其他的元素了。为什么是void*类型的呢?这里可以把void*理解成一个收容所,各种各样的数据的地址都可以放在void*里面。由于qsort可以对几乎任意的类型数据进行快排,因此需要一个可以接受任意类型的指针。

②第二个参数size_t num也就是元素的个数。知道了首元素的地址,相当于知道了“起点”在哪,我们还需要知道终点才能准确地取出数据。

③第三个参数size_t size,也就是每个元素类型的长度(单位是字节)。知道了起点和终点找出了相对应的数据,但是我们需要逐个对元素进行比较才能排序。因此知道每个元素类型的长度,就可以知道每个元素。

④第四个参数int(*compar)(const void*,const void*).他的返回值是为1,0,-1.这个函数相当于比较的标准,需要我们自定义。const对其进行修饰,只进行比较,不能进行修改。这是比较的关键。

下面我们先来对不同类型的数据进行qsort,体会一下qsort是如何使用的。

一 对int类型的数据进行升序排列

#define _CRT_SECURE_NO_WARNINGS 1 
#include<stdio.h>
#include<stdlib.h>
int cmp_int(const void* e1, const void* e2)
{
	return*(int*)e1 - *(int*)e2;
}
int main()
{
	
	int arr[10] = { 1,2,3,80,6,79,43,25,36,66 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	int single_len = sizeof(arr[0]);
	printf("排序之前的序列:");
	for (int i = 0; i < sz ; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");

	qsort(arr, sz,single_len, cmp_int);
	printf("排序之后的序列:");
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
	return 0;
}

二 对char类型的数据按照字典顺序进行排列

#define _CRT_SECURE_NO_WARNINGS 1 
#include<stdio.h>
#include<stdlib.h>

int cmp_char(const void* e1, const void* e2)
{
	return *(char*)e1- *(char*)e2;
}
int main()
{
	char arr[10] = { 'a','v','e','d','s','z','q','w','p','\0' };
	int sz = sizeof(arr) / sizeof(arr[0]);
	int single_lenth = sizeof(arr[0]);
	printf("排序前的序列:");
	for (int i = 0; i < sz; i++)
	{
		printf("%c ", arr[i]);
	}
	printf("\n");
	qsort(arr, sz, single_lenth, cmp_char);
	printf("排序后的序列:");
	for (int i = 0; i < sz; i++)
	{
		printf("%c ", arr[i]);
	}

	return 0;
}

由于字符在内存中是按照ASCLL码表上的数字进行排列的,因此比较大小可以直接相减,类比int。

三 浮点类型的数据进行排列

#define _CRT_SECURE_NO_WARNINGS 1 
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int cmp_float(const void* e1, const void* e2)
{
	return ((*(float*)e1 > *(float*)e2) ? 1:-1);
}
int main()
{
	float arr[] = { 1.11,5.55,4.32,6.21,7.56 };
	printf("排序前的序列:");
	int sz = sizeof(arr) / sizeof(arr[0]);
	int single_lenth = sizeof(arr[0]);
	for (int i = 0; i < sz; i++)
	{
		printf("%.2f ", arr[i]);
	}
	printf("\n");

	qsort(arr,sz,single_lenth,cmp_float);
	printf("排序后的序列:");
	for (int i = 0; i < sz; i++)
	{
		printf("%.2f ", arr[i]);
	}

	return 0;
}

需要注意的是compar需要返回int类型的数据,所以需要转换一下。

了解了qsort的一个使用方法。能不能让冒泡排序也具有兼容性呢?

使用上qsort就可以!

下面模拟使用qsort来对冒泡排序的适用范围进行扩展。从int类型上手:

#define _CRT_SECURE_NO_WARNINGS 1 
#include<stdio.h>

void swap(char* buf1, char* buf2, int single_lentth)
{
	for (int i = 0; i < single_lentth; i++)
	{
		char ret = *buf1;
		*buf1 = *buf2;
		*buf2 = ret;
		buf1++;
		buf2++;
	}
}

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

void bubble_sort(void* base, int sz, int single_lenth, int(*cmp_int)(const void* e1, const void* e2))
{
	for (int i = 0; i < sz - 1; i++)
	{
		for (int j = 0; j < sz - 1 - i; j++)
		{
			if (cmp_int((char*)base + j * single_lenth, (char*)base + (j + 1) * single_lenth) > 0)
			{
				swap((char*)base + j * single_lenth, (char*)base + (j + 1) * single_lenth, single_lenth);
			}
		}
	}
}
int main()
{
	int arr[10] = { 1,5,3,92,5,34,78,0,66,69 };
	
	int sz = sizeof(arr) / sizeof(arr[0]);
	int single_lenth = sizeof(arr[0]);
	printf("交换前:");
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
	//交换前
	bubble_sort(arr, sz, single_lenth, cmp_int);
	printf("交换后");
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");

	return 0;
}

关于if条件中为什么使用char*。因为char*解引用之后一次只访问的一个字节的数据,方便对内存中的数据进行逐一交换。如果是int*的话可以用于int类型的排序,但是兼容性并没有那么好。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值