qsort的理解--加强对指针的理解

前言:前面我们学习指针变量数组指针变量函数指针变量;这些实际上都是变量实质上是在内存中开辟一块空间;而这些变量存储的都是地址。还有指针数组,函数指针数组,这指的是把多个地址存在数组中,要注意分别。


回调函数

在将qort之前,先来引入一个回调函数的概念。

回调函数就是一个通过函数指针调用的函数。

如果你把函数指针(地址)作为参数传给另一个函数,当这个指针被用来调用其所指向的函数,这就是回调函数。

 


 冒泡排序

冒泡排序的核心思想就是:俩俩相邻的元素进行比较。


问题与解答(递进式解决)

1. 问题如果我们有10个元素,要进行几次排序?

回答:首先,进行第一次排序,把最大的一个数字排在最右边然后就不用再和别的数字进行比较。最后一个数字不用比较,直接固定。所以要进行9次排序

 


2.问题那10个元素需要比较几次?

 回答:对于第一次排序,有10个元素,需要进行9对比较;第二次,最大数字固定好了,就9个元素,进行8对比较依次类推。


 

#include <stdio.h>
void bubble_sort(int arr[], int sz) //参数接收的元素的个数
{
	int i = 0;
	int j = 0;
	for (i = 0; i < sz - 1; i++) //循环n-1次
	{
		for (j = 0; j < sz - 1 - i; j++)
		{
			if (arr[j] > arr[j + 1])
			{
				int bottle = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = bottle;
			}
		}
	}
}
void print_sort(int arr[], int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}


}

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

	return 0;
}

 


 

qsort函数使用

qsort--库函数,它可以实现任意类型数据的排序。它用是快速排序。 默认升序

qsort函数底层使用了回调函数的方式 。

  1. 今天学习qsort的使用
  2. qsort函数的实现原理,模拟实现一下(冒泡排序的思想)。

先来看一下语法:

 

 void qsort(void* base, //base中存放的是待排序数组的第一个元素的地址

 size_t num, //num存放的是base指向的数组中的元素个数

 size_t size, //size是base指向的数组中一个元素的长度,单位是字节

 int (*compar)(const void*e1, const void*e2) //函数指针-指向了一个比较函数,这个比较函数是用来比较数组中的两个元素的

如果e1指向的元素大于e2指向的元素,那么函数返回>0的数字

如果e1指向的元素等于e2指向的元素,那么函数返回0

如果e1指向的元素小于e2指向的元素,那么函数返回<0的数字

 );


 qsort对整型的排序

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

Print(int* p, int len)
{
	int i = 0;
	for (i = 0; i < len; i++)
	{
		printf("%d ", *(p + i));
		

	}
}

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

int main()
{
	int arr[] = { 3,2,6,5,8,4,10,9,7 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	qsort(arr, sz, sizeof(arr[0]), compare);
	Print(arr, sz);
	return 0;
}


 qsort对结构体的排序

struct Stu
{
	char name[200];
	int age;
};

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

int main()
{

	struct Stu s[3] = { {"zhangsan", 25 }, {"lisi", 98 }, {"wangwu", 11 } };
	int sz = sizeof(s) / sizeof(s[0]);
	qsort(s, sz, sizeof(s[0]), cmp_stu_by_name);
	return 0;
}

 


  如图,我们可以知道qort默认排序是升序,只需要写一个比较函数它就能给出排序的结果


 qsort函数的实现原理,模拟实现一下(冒泡排序的思想)。

int main()
{
	test();
	return 0;
}

 通过函数调用实现复杂的逻辑

void test()
{
	int arr[] = { 3,2,6,5,8,4,10,9,7 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	bubble_sort(arr, sz, sizeof(arr[0]), compare);
	Print(arr, sz);
}

 

void bubble_sort(void* base, size_t sz, size_t size, int (*pf)(const void* e1, const void* e2))
{
	int i = 0;
	int j = 0;
	for (i = 0; i < sz - 1; i++)
	{
		for (j = 0; j < sz - i - 1; j++)
		{
			//arr[j] > arr[j + 1];
			if (pf((char*)base + j * size, (char*)base + (j + 1) * size) > 0)
			{
				swap((char*)base + j * size, (char*)base + (j + 1) * size, size);
			}
		}
	}
}

 首先,参数是void,因为不知道传过来的参数是什么,所以用void接收。接下来,把传过来的数据强制类型转换成为字符指针类型,这样每个字节的内容都不会遗漏。

当进入pf函数的时候,就会指向比较函数,这就是回调函数。

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

当符合判断条件的时候,就会进行字节交换

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

 接下来,看一下整体的代码。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void swap(char* p, char* p2, size_t size)
{
	int i = 0;
	for (i = 0; i < size; i++)
	{
		char tmp = *p;
		*p = *p2;
		*p2 = tmp;
		p++;
		p2++;
	}
}

void bubble_sort(void* base, size_t sz, size_t size, int (*pf)(const void* e1, const void* e2))
{
	int i = 0;
	int j = 0;
	for (i = 0; i < sz - 1; i++)
	{
		for (j = 0; j < sz - i - 1; j++)
		{
			//arr[j] > arr[j + 1];
			if (pf((char*)base + j * size, (char*)base + (j + 1) * size) > 0)
			{
				swap((char*)base + j * size, (char*)base + (j + 1) * size, size);
			}
		}
	}
}

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

void test()
{
	int arr[] = { 3,2,6,5,8,4,10,9,7 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	bubble_sort(arr, sz, sizeof(arr[0]), compare);
	Print(arr, sz);
}

int main()
{
	test();
	return 0;
}

 

希望对你有帮助,喜欢的点个赞 。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值