前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >深度剖析C语言库函数之强大的排序函数qsort并且模拟实现

深度剖析C语言库函数之强大的排序函数qsort并且模拟实现

作者头像
换一颗红豆
发布2024-12-20 10:57:38
发布2024-12-20 10:57:38
17600
代码可运行
举报
运行总次数:0
代码可运行

1.qsort的定义

学习之前 首先我们来看一下C语言标准库给出的定义

qsort函数的头文件是<stdlib.h>

Sort elements of array 表示qsort的功能是排序数组的元素,不难发现它的返回类型为void 接下来我们来仔细分析下它的四个参数:

第一个参数是指针base,指向要被排序的数组中第一个元素,也就是数组名。  类型为void*

第二个参数为num,表示排序的数组中的元素个数, 类型是sizt_t

第三个参数是size,表示排序数组中一个元素的字节大小,类型同样是size_t

前三个参数不用过多解释,最后一个参数我们重点讲解一下!

最后一个参数compar:是使用者传过来的一个函数指针指向用来比较两个元素的函数 这个函数被qsort反复调用以比较两个元素。应遵循以下原型:

Int (const void* p1, const void* p2); 函数参数为两个void*类型的指针p1和p2

这里需要注意​void*类型的指针不能直接解引用,需要强制类型转换为对应的类型在解引用!

函数返回类型为int,通过函数的返回值来对数组元素进行排序。根据返回值有下列排序情况

<0 p1所指向的元素在p2所指向的元素之前 =0 p1指向的元素和p2指向的元素是等价的 >0 p所指向的元素在p2所指向的元素之后

2.不同类型参数下compar函数的返回值问题

int 类型:

代码语言:javascript
代码运行次数:0
复制
int int_cmp(const void* p1, const void* p2)
{
	return (*(int*)p1 - *(int*)p2);
}

char类型:

代码语言:javascript
代码运行次数:0
复制
int char_cmp(const void* p1, const void* p2)
{
	return (*( char*)p1 - *(char*)p2);
}

double类型:注意由于double类型的精度有限,这里我们使用三目操作符直接判断

代码语言:javascript
代码运行次数:0
复制
int double_cmp(const void* p1, const void* p2)
{
	return (*(double*)p1 > *(double*)p2 ? 1 : -1); 
}

结构体类型:

代码语言:javascript
代码运行次数:0
复制
//我们声明一个结构体
struct Stu //学生
{
	char name[20];//名字
	int age;//年龄
	char id[20]//学号
};

//假设按照年龄来排序
int cmp_stu_by_age(const void* p1, const void* p2)
{
	return ((struct Stu*)p1)->age - ((struct Stu*)p2)->age;
}

//假设按照名字排序
int cmp_stu_by_name(const void* p1, const void* p2)
{
	return strcmp(((struct Stu*)p1)->name, ((struct Stu*)p2)->name);//strcmp用来比较两个字符串大小
}

//按照学号排序
int cmp_stu_by_id(const void* p1, const void* p2)
{
	return strcmp(((struct Stu*)p1)->id, ((struct Stu*)p2)->id);
}

3.qsort函数的简单应用

下面我们来简单使用一下qsort 排序一个整形数组进行升序排序

代码如下:

代码语言:javascript
代码运行次数:0
复制
#include <stdio.h>
#include<stdlib.h>
//qosrt函数的使用者需要自己实现一个比较函数
int int_cmp(const void* p1, const void* p2)
{
	return (*(int*)p1 - *(int*)p2);//这里我们要求排序为升序
}
int main()
{
	//利用qsort对下面这个无序整形数组排序
	int arr[] = { 1, 3, 5, 7, 9, 2, 4, 6, 8, 0 };
	int i = 0;
	//调用qsort
	qsort(arr, sizeof(arr) / sizeof(arr[0]), sizeof(int), int_cmp);
	for (i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
	return 0;
}

代码运行结果如下:

我们再来看一组char类型数据的排序:

代码语言:javascript
代码运行次数:0
复制
#include <stdio.h>
#include <stdlib.h>

int char_cmp(const void* p1, const void* p2)
{
	return *(char*)p1 - *(char*)p2; //要求升序
}

int main()
{
	char arr[] = { 'f', 'b','e','a','d','c' };
	int sz = sizeof(arr) / sizeof(arr[0]);


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

	for (int i = 0; i < sz; i++)
	{
		printf("%c ", arr[i]);
	}
	return 0;
}

对double类型数据进行qsort排序:

代码语言:javascript
代码运行次数:0
复制
int double_cmp(const void* p1, const void* p2)
{
	return (*(double*)p1 > *(double*)p2 ? 1 : -1); 
}

void test02()
{
	double arr[] = { 3.14,2.6,2.3,1.7 };
	int sz = sizeof(arr) / sizeof(arr[0]);


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

	for (int i = 0; i < sz; i++)
	{
		printf("%lf ", arr[i]);
	}

}
int main()
{
	test02();

	return 0;
}

排序结果:

我们在使用qsort对结构体类型数据排序一次代码如下:

代码语言:javascript
代码运行次数:0
复制
struct Stu //学⽣
{
	char name[20];//名字
	int age;//年龄
};
int cmp_stu_by_name(const void* p1, const void* p2)
{
	return strcmp(((struct Stu*)p1)->name, ((struct Stu*)p2)->name);//我们要求升序排序
}
void test0()
{
	struct Stu s[] = { {"zhangsan", 20}, {"lisi", 30}, {"wangwu", 15} };
	int sz = sizeof(s) / sizeof(s[0]);
	qsort(s, sz, sizeof(s[0]), cmp_stu_by_name);
	//我们观察下排序后的排列情况
	for (int i = 0; i < sz; i++)
	{
		printf("%s,%d ", s[i].name, s[i].age);
	}
}
int main()
{
	test0();
	return 0;
}

程序运行结果如下:

4.接下来我们模拟实现qsort对各种类型的数据实现冒泡排序!

上代码!

代码语言:javascript
代码运行次数:0
复制
//模拟qsort编写一个函数实现对各种数据的冒泡排序
int comp_t(const void* p1, const void* p2)
{
	return *(int*)p1 - *(int*)p2;
}

void Swap(void* p1, void* p2, int size)
{
	int i = 0;
	for (i = 0; i < size; i++)
	{
		char tmp = *((char*)p1 + i);
		*((char*)p1 + i) = *((char*)p2 + i);
		*((char*)p2 + i) = tmp;
	}
}


void my_bubble_sort(void* base, size_t sz, size_t width, int (*cmp)(const void* p1, const void* p2))
{
	//趟数
	int i = 0;
	for (i = 0; i < sz - 1; i++)
	{
		//一趟内部的两两比较
		int j = 0;
		for (j = 0; j < sz - 1 - i; j++)
		{
			//比较arr[j] 和 arr[j + 1]
			if (cmp((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[] = { 1,4,7,2,5,0,8,9,6,3 };
	int i = 0;
	my_bubble_sort(arr, sizeof(arr) / sizeof(arr[0]), sizeof(int), comp_t);
	for (i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

冒泡排序结果如上!

好了到此为止我们所有关于qsort函数的讲解就结束了,那么本期内容就到这里,如果对你有帮助记得一键三连,如果有不足的地方欢迎各位大佬指正!更多精彩内容敬请期待!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-12-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.qsort的定义
    • 2.不同类型参数下compar函数的返回值问题
    • 3.qsort函数的简单应用
    • 4.接下来我们模拟实现qsort对各种类型的数据实现冒泡排序!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档