利用冒泡排序实现快速排序

目录

前言

一、冒泡排序

二、快速排序的实现

1.qsort的底层逻辑

2.Bubble_sort的改进

(1)比较的改进

(一)整型

(二)结构体类型 

(2) 交换的改进

三.完整代码


前言

上文说到回调函数的使用,本文就应用回调函数实现快速排序吧!!!

一、冒泡排序

在上文已经写过Bubble_sort的函数,这里就不在讲解,直接上代码。

void bubble_sort(int arr[], int sz)
{
    //冒泡排序的趟数
    int i = 0;
    for (i = 0; i < sz - 1; i++)
    {
	    //一趟冒泡排序
	    int j = 0;
	    for (j = 0; j < sz-1-i; j++)
	    {
		    if (arr[j] > arr[j + 1])
		    {    
			    int tmp = arr[j];
			    arr[j] = arr[j + 1];
			    arr[j + 1] = tmp;
		    }
	   }
    }
}

二、快速排序的实现

1.qsort的底层逻辑

小小周哦

qsort 底层使用的快速排序
void qsort( void* base, //待排序数据的起始地址
                    size_t num, //待排序数据的元素个数
                    size_t size,  //待排序数据的一个元素的大小,单位是字节
                    int (*cmp)(const void*, const void*)//函数指针 - 指向了一个比较函数,这个函数是用来比较2个元素的);

2.Bubble_sort的改进

仿照qsort的函数参数,我们可以知道实现的关键就是比较交换这两部分。

void bubble_sort(void* base, size_t num, size_t size, int (*cmp)(const void* e1, const void*e2))
{
	//冒泡排序的趟数
	int i = 0;
	for (i = 0; i < num - 1; i++)
	{
		//一趟冒泡排序
		int j = 0;
		for (j = 0; j < num - 1 - i; j++)
		{
			//比较......
			{
				//交换......
			}
		}
	}
}

(1)比较的改进

如果想实现各种数据类型的排序,比较只用if (arr[j] > arr[j + 1]) 是远远不够的,比如遇到结构体的时候,该比较方法就不再适用了。这时我们可以换种思路,通过比较每一个字节来判断大小。此时就要用到函数指针了,也就是int (*cmp_type)(const void* e1, const void*e2),该函数需要使用者根据数据类型自行编写。然后在冒泡排序内部比较时调用该函数。为了逐个字节比较,可以使用(char*)base,强制转化为字符型指针,使每次后移时只移动一个字节。(char*)base + j * size为“第一个字节”的地址,所以“下一个字节”的地址为(char*)base + (j + 1) * size,这样Bubble_sort内比较部分需要传的参数就固定啦!

int (*cmp)(const void* e1, const void* e2)
e1是一个指针,存放了一个要比较的元素的地址
e2是一个指针,存放了一个要比较的元素的地址
e1指向的元素>e2指向的元素,返回>0的数字
e1指向的元素==e2指向的元素,返回0
e1指向的元素<e2指向的元素,返回<0的数字

//比较部分
if(cmp((char*)base + j * size, (char*)base + (j + 1) * size)>0)

 下面就给出两种数据类型cmp函数吧

tips:void* 不可以比较大小哦!!!记得强制转换类型!!!

(一)整型
int cmp_int(const void*e1, const void*e2)
{
	return *(int*)e1 - *(int*)e2;
}
(二)结构体类型 
struct Stu
{
	char name[20];//20个字节
	int age;      //4个字节
};

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


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

(2) 交换的改进

既然比较是逐个字节比较,那交换也是如此,只不过要注意的是,需要把该数据完整的交换,所以与普通的交换函数相比,多了一个参数size,此时便能完整交换需要比较的数据。

这里选择用char*作为参数数据类型也正是因为它刚好能够达到交换一个字节的效果。

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

三.完整代码

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

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

void bubble_sort(void* base, size_t num, size_t size, int (*cmp)(const void* e1, const void*e2))
{
	//冒泡排序的趟数
	int i = 0;
	for (i = 0; i < num - 1; i++)
	{
		//一趟冒泡排序
		int j = 0;
		for (j = 0; j < num - 1 - i; j++)
		{    
            //比较
			if(cmp((char*)base + j * size, (char*)base + (j + 1) * size)>0)
			{
				//交换
				swap((char*)base + j * size, (char*)base + (j + 1) * size, size);
			}
		}
	}
}

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值