qsort — c语言中自带的排序函数(附带void*、回调函数知识点

       因为总是忘记有qsort这个函数,导致遇到需要排序的题的时候,总是要写着类似的代码,所以特此单独把qsort拿出来单独整理一遍,让自己能够熟练掌握,也以免之后忘记了qsort可以拿自己的文章看。

目录

一、论冒泡排序和qsort

1、qsort 是什么?

2、qsort在程序中使用

1.关于cmp函数的一些规定 

2、介绍一个指针类型 void*类型

         3、模拟qsort

二、回调函数

三、在最后



一、论冒泡排序和qsort

       冒泡排序的核心思想:相邻元素两两比较

  写一个冒泡排序函数:


#include

void bubble_sort(int arr[], int sz);//函数声明

int  main()
{
	//先创建一个数组
	int arr[] = { 4,8,9,3,5,2,1,7 };

	//通过sizeof求元素个数
	int sz = sizeof(arr) / sizeof(arr[0]);

	//把数组排成升序
	bubble_sort(arr, sz);

	//打印数组内容
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

//这个函数只能排整型数组
void bubble_sort(int arr[], int sz)
{
	int i = 0;

	while (sz)
	{
		int flag = 0;
		for (i = 0; i < sz - 1; i++)
		{
			if (arr[i] > arr[i + 1])//元素两两比较
			{
				int tmp = arr[i];
				arr[i] = arr[i + 1];
				arr[i + 1] = tmp;
				flag = 1;
			}
		}
		sz--;
		if (flag == 0)
		{
			break;//如果数组内容一开始就是按规则有序排列的,可以进行判断优化
		}
	}
}

       请注意:这样的冒泡排序有一个弊端只能排序整型数据,因为在最开始函数定义的时候已经把参数写死了。

       下面开始介绍一个库函数qsort


1、qsort 是什么?

  qsort是一个使用快速排序的思想实现的一个排序函数。

  并且qsort 可以排序任意类型的数据。

下面是关于qsort函数参数的介绍:


void qsort(void* base, size_t num, size_t size,
	int (*cmp)(const void* e1, const void* e2));
//
//void* base 你要排序的数据的起始位置
//size_t num 待排序的数据元素的个数
//size_t size 待排序的数据元素的大小(单位是字节)
//int (*cmp)(const void* e1, const void* e2)) 
   //函数指针-比较函数 cmp就是一个比较函数的地址,也就是这个比较函数的函数指针
   //e1指向了你要比较的第一个元素  e2指向了你要比较的第二个元素
   //e1 e2 是你要比较的两个元素的地址


2、qsort在程序中使用

   写一个程序使用一下:


#include
#include

int cmp_int(const void* e1, const void* e2);

int  main()
{
	//先创建一个数组
	int arr[] = { 4,8,9,3,5,2,1,7 };

	//通过sizeof求元素个数
	int sz = sizeof(arr) / sizeof(arr[0]);

	qsort(arr, sz, sizeof(arr[0]), cmp_int);

	//打印数组内容
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

//比较两个整型元素
//这样排序默认是升序排列
//
int cmp_int (const void*e1,const void*e2)
{	
	return (* (int*)e1 - *(int*)e2);//所以比较的时候要强制类型转换一下
}


1.关于cmp函数的一些规定 

       注意其对于函数参数所传递的void*指针的解应用需要进行强制类型转换,比较什么类型的数据,就强制类型转换成什么类型,随后进行比较。

       注意返回值规定
               //e1指向的元素 > e2指向的元素 返回值 >0
               //e1指向的元素 = e2指向的元素 返回值 =0
               //e1指向的元素 < e2指向的元素 返回值 <0

  默认这样传递返回值,是升序排列。

//这样排序默认是升序排列
//
int cmp_int (const void*e1,const void*e2)
{	
	return (* (int*)e1 - *(int*)e2);//所以比较的时候要强制类型转换一下
}
//注意规定:
	//e1指向的元素 > e2指向的元素 返回值 >0
	//e1指向的元素 = e2指向的元素 返回值 =0
	//e1指向的元素 < e2指向的元素 返回值 <0

  如果想要变成降序排列

  可以改变e1 e2相减位置,或者直接整体加负号使其逻辑相反即可。

//如果想改成降序排列
//可以改变e1 e2相减位置,或者直接整体加负号使其逻辑相反即可

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

插入一个知识点:


2、介绍一个指针类型 void*类型

  论void*的包容性:

       void*的指针是无具体类型的指针,可以接受任意类型的地址。是不能直接进行解应用操作的,也不能进行+ -整数的操作。

       注意在使用指针指向的内容的时候,要对其强制类型转换再解引用。  


3、模拟qsort

  注意在my_qsrt中向cmp传参时的强制类型转换:       

    在这里传参比较的时候不能直接传递void*类型的 arr,void*类型的数据不能加减操作。

    将void*类型强制转换成最小类型char*类型,后续根据len进行步长的加减。


    根据cmp返回参数规定,以及qsort默认排列升序,所以是 >0。

//模拟qsort

#include

void my_qsort(void* arr, int sz, int len, int cmp(void* e1, void* e2));
int cmp_int(const void* e1, const void* e2);

int main()
{
	int arr[] = { 1,2,5,4,7,8,6,3,9 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	my_qsort(arr, sz, sizeof(arr[0]), cmp_int);
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	return;
}

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

void my_qsort(void* arr, int sz, int len, int cmp(const void* e1, const void* e2))
{
	int i = 0;
	while (sz)
	{
		int flag = 0;
		for (i = 0; i < sz - 1; i++)
		{
			//注意这里传参比较的时候不能直接传递arr,void*类型的数据不能加减操作
			//将void*类型强制转换成最小类型char*类型,后续根据len进行步长的加减
			//根据cmp返回参数规定,以及qsort默认排列升序,所以是 >0
			if (cmp((char*)arr + len * i, (char*)arr + len * (i + 1) )> 0)
			{
				int tmp = *((char*)arr + len * i);
				*((char*)arr + len * i) = *((char*)arr + len * (i + 1));
				*((char*)arr + len * (i + 1)) = tmp;
				flag = 1;
			}
		}
		sz--;
		if (flag == 0)
		{
			break;
		}
	}
}

二、回调函数

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

        !注意:回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。(就比如在使用qsort函数的时候调用的cmp函数


三、在最后

       第一次写完一个正式的关于知识点的博客,vpurple表示自己很开心哈哈哈,这次费的时间还挺长的,还是对这个编辑器运用不熟练www,不过在写这个博客的时候又重新复习了一遍,真的希望要把它记在心里呜呜呜

      反思一下其实我对于c语言后半部分的知识点基本功都不太扎实,还是要趁着暑假期间把它们全都顺一遍,坚持日更!!!flag反正是立在这里了www绝对不会打脸的!!!

       还有在最后祝我早日对于qsort函数使用烂熟于心,还有void*和回调函数这些知识点,全都记住!!!

你可能感兴趣的:(c语言进阶之路,开发语言,c语言,排序算法)