qsort快速排序

 qsort()函数(quick sort)是八大排序算法中的快速排序,能够排序任意数据类型的数组其中包括整形,浮点型,字符串甚至还有自定义的结构体类型。

我们分析一下它的参数:

base:它指向需要排序的首元素的地址,是一个void*的指针;

num:需要排序的元素个数

size:每个元素的大小

int (*compar)(const void*, const void*):这是一个函数指针,这个函数指针指向的函数,能够比较base指向的数组中相邻两个元素的大小。(需要自己设计

注意:

  • 使用这个函数要包含的头文件是:
#include<stdlib.h>
  • 此函数默认是从小到大排序

举个例子:

#include<stdio.h>
#include<stdlib.h>

int compar(const void* p1, const void* p2)
{
	return *((int*)p1) - *((int*)p2);
}
void print(int* p, int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", *(p + i));
	}
	printf("\n");
}
int main()
{
	int arr[10] = { 9,8,7,6,5,4,3,2,1,0 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	qsort(arr, sz, sizeof(int), compar);
	print(arr, sz);
	return 0;
}

这里我们比较的是整形数据,所以compar函数的指针就要强转成int*再解引用。

也可以比较字符串,比较结构体类型的数据,其主要就是在compar函数里看情况设计。

我们再举个例子,比如比较结构体类型的字符串:

struct stu
{
    char name[5];
    int age;
};

compar函数可以这样设计

int compar(const void* p1, const void* p2)
{
    return strcmp((struct stu*)p1->name, (struct stu*)p2->name);
}

懂了它的原理,我们开始模拟实现:

我们需要解决的地方主要有三:

  • 解决1:void*指针,元素个数,元素大小
  • 解决2:将两个元素比较方法,用函数参数的形式传递
  • 解决3:不同的数据类型,交换略有差异

首先我们得有主函数,就跟上面的例子一样。

int main()
{
	int arr[10] = { 9,8,7,6,5,4,3,2,1,0 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	bubble(arr, sz, sizeof(int), compar);
	print(arr, sz);
	return 0;
}

然后就是bubble函数的实现啦:

首先设计它的返回类型,函数参数,因为是模拟实现嘛,就跟它原本的差不多啦。

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

它的基本思想是通过不断比较相邻的元素,将较大的元素向后移动,较小的元素向前移动,从而实现排序的目的。

一趟排一个元素,只剩最后一个元素的时候已经不用排序了,所以趟数就是要比较的元素个数减1。确定之后就是比较相邻元素的大小了,我们就设计compar这个函数比较,小的在前大的在后,不符合就交换,所以还需要设计一个函数帮我们交换。

以上就是思路,具体实现一下:

void bubble(void* base, size_t num, size_t size, int (*cmp)(const void*, const void*))
{
	int i = 0;
	//趟数
	for (i = 0; i < num - 1; i++)
	{
		int j = 0;
		//一趟比较的对数
		for (j = 0; j < num - 1 - i; j++)
		{
			//比较两个相邻元素,要将数组的第一个元素和第二个元素地址传进去
			if (compar((char*)base + j * size, (char*)base + (j + 1) * size) > 0)//因为类型不确定,要强转成最小的类型char*再加j乘以类型大小,就是跳过几个字节
			{
				//交换
				swap((char*)base + j * size, (char*)base + (j + 1) * size, size);
			}
		}
	}
}

然后是compar函数:

注意这里是根据你要比较的类型确定强转成什么类型,而且到底是比较字符串还是数字这都是视情况来定的。(这里以int类型的数据比较)

int compar(const void* p1, const void* p2)
{
	return *(int*)p1 - *(int*)p2;
}

比较之后,不符合小的在前的要交换,设计swap函数来帮我们实现:


void swap(char* buf1, char* buf2, size_t size)
{
	int i = 0;
	char tmp = 0;
	for (i = 0; i < size; i++)//例如,一个整形四个字节,要一个一个交换,所以i < size
	{
		tmp = *buf1;
		*buf1 = *buf2;
		*buf2 = tmp;
		buf1++;
		buf2++;
	}
}

这个函数要传两个需要交换的元素的地址,和字节大小。因为要交换的类型不确定,只能一个字节一个字节交换,我们用char*的指针。

以上整体就是实现的具体方法。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值