qsort的使用与实现

 c语言常见的排序方法大概有这些,今天我们所讲的是就是qsort快排的讲解

 头文件

 qsort的使用

 我们先使用msdn查看他的相关资料,得知这个函数的传参请情况

 1.void *base

 翻译过来就是将要排序的函数的起始位置/数组首元素地址

2.size_t num 

 翻译过来就是数组个数(要注意这里的个数是指该数组元素的个数,单位是个)

3.size_t width 

 翻译过来就是每个元素大小(以字节计)

4. int (__cdecl *compare )(const void *elem1, const void *elem2 )

最后一个参数看起来很长,但实际看起来,他就是一个函数指针 ,我们看看在msdn上他的解释是什么

 compare                       elem1                                     elem2

[数] 比较函数              指向搜索键的指针                指向要与键进行比较的数组元素的指针

 经过阅读以上文章得知,compare函数的作用便是

compare( (void *) elem1, (void *) elem2 );

所以我们便不难实现compare函数 

返回类型为int   两个形参全都是void*

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

以上就是通过msdn查阅资料得知其功能,从而得知其的使用方法

以下排序展示效果

#include <stdio.h>
#include <stdlib.h>
int compare(const void* e1, const void* e2)
{
	return (*(int*)e1 - *(int*)e2);
}
int main()
{
	int arr[10] = { 8,5,2,3,6,4,1,7,9,0 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	qsort(arr, sz, sizeof(arr[0]),compare);
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

代码运行起来便是如此效果

当然降序只需要将第四个参数的逻辑该反,具体就是如下

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

qsort排序结构体

上文的使用只在整形数组内使用了,但如果是结构体的话使用会不会又不同呢?

我们带着这个疑问,对上文的代码进行改进,使其可以对结构体排序;

#include <stdio.h>
#include<stdlib.h>
struct stu
{
	char name[20];
	int age;
	char sex[5];
};
int compare(const void* e1, const void* e2)
{
	return (*(int*)e1 - *(int*)e2);
}
int main()
{
	struct stu s[3] = { {"李四",20,"男"},{"王五",20,"男"} ,{"赵四",20,"男"} };
	int sz = sizeof(s) / sizeof(s[0]);
	qsort(s, sz, sizeof(s[0]),compare);
	int i = 0; 
	for (i = 0; i < sz; i++)
	{
		printf("%s %d %s\n", s[i].name, s[i].age, s[i].sex);
	}
	return 0;
}

貌似也是可以行的通的,但是思考过后,发现我们是以什么方式排序的呢?我们没有修改第四个形参的函数的内部修改,第四个形参的作用就意在说明我们是利用什么方式在排序,(结构体以名字排序)那么我们就对于不同的类型要使用不同的compare,

以下代码 便是compare 通过name

#include<string.h>
int com_name(const void* e1, const void* e2)
{
	return (strcmp(((struct stu*)e1)->name, ((struct stu*)e2)->name));
}//这里一定要记得强制类型转换

qsort的实现(排序整形)

 qsort我们会用以后,那么就要去尝试着怎么自己实现,

我们先看以下冒泡排序的实现方法

void Bubble_sort(int arr[], int size)//int arr[]等价于int *arr
{
	int j, i;
	for (i = 0; i < size - 1; i++)//size-1是因为不用与自己比较,所以比的数就少一个
	{
		int count = 0;
		for (j = 0; j < size - 1 - i; j++)	//size-1-i是因为每一趟就会少一个数比较
		{
			if (arr[j] > arr[j + 1])//这是升序排法,前一个数和后一个数比较,如果前数大则与后一个数换位置
			{
				int tem = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tem;
				count = 1;

			}
		}
		if (count == 0)			//如果某一趟没有交换位置,则说明已经排好序,直接退出循环
			break;
	}
}
int main()
{
	int arr[10] = { 9,8,7,6,5,4,3,2,1,0 };
	int i = 0;
	Bubble_sort(arr, 10);
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

 所标红的地方便是相当于qsort里面第四个参数(比较),我们在冒泡排序实现代码基础上进行修改

对于实现者:不知道排序的是什么类型的数组
对于使用者:知道其排序的是什么类型的数组
所以使用去qsort最重要的是对于不同类型使用的com(第四个参数)是不同的

对于第一个参数

msdn上是void*类型的,void*类型的好处就是可以接受任何类型的地址,利用这一点就可以排序任何类型的数组

对于第二个参数跟冒泡排序的参数sz一样,第三个参数与第一个参数结合,不就是解释了每个元素大小(把第一个参数强制类型转化为char*)(也大致就了解是什么类型)达到了冒泡排序第一个参数作用

修改参数:

void Bubble_sort(void* base, 
	size_t num, 
	size_t width, 
	int (*com)(const void* e1, const void* e2)
)

大致思路路就是

 com(比较大小)

if (com((char*)base + j * width, (char*)base + (j + 1) * width)>0)

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

swap(交换)

swap((char*)base + j * width, (char*)base + (j + 1) * width, width);

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

总结

#include<stdio.h>
void swap(char* buf1, char* buf2, int width)
{
	int i = 0;
	for (i = 0; i < width; i++)
	{
		char tmp = *buf1;
		*buf1 = *buf2;
		*buf2 = tmp;
		buf1++, buf2++;
	}
}
int com(const void* e1, const void* e2)
{
	return *(int*)e1 - *(int*)e2;
}
void Bubble_sort(void* base,size_t num,size_t width,int (*com)(const void* e1, const void* e2))
{
	int j, i;
	for (i = 0; i < num - 1; i++)
	{
		int count = 0;
		for (j = 0; j < num - 1 - i; j++)
		{
			if (com((char*)base + j * width, (char*)base + (j + 1) * width)>0)
			{
					swap((char*)base + j * width, (char*)base + (j + 1) * width, width);
			}
		}
	}
}	
int main()
{
	int arr[10] = { 9,8,7,6,5,4,3,2,1,0 };
	int i = 0;
	int sz = sizeof(arr) / sizeof(arr[0]);
	Bubble_sort(arr, sz, sizeof(arr[0]), com);
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

 排序结构体的数组只需要改变com函数即可

  • 30
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值