qsort函数的应用以及模拟实现

news2024/12/24 3:37:46

在这里插入图片描述

前言

🎈个人主页:🎈 :✨✨✨初阶牛✨✨✨
🐻推荐专栏: 🍔🍟🌯 c语言进阶
🔑个人信条: 🌵知行合一
🍉本篇简介:>:介绍库函数qsort函数的模拟实现和应用
金句分享:

✨追光的人,终会光芒万丈.✨

目录

  • 前言
  • 一、qsort函数介绍
  • 二、qsort函数的应用
    • 1.整形数组排序
    • 2.浮点型数组排序
    • 3.字符型排序
    • 4.结构体数组排序
  • 三、qsort模拟实现(采用冒泡排序模拟)
    • 第一步:冒泡函数的参数
    • 第二步:比较元素的的方法
    • 第三步:交换函数

一、qsort函数介绍

库函数查询网站(建议使用旧版本查询)

在这里插入图片描述
头文件:<stdlib.h>

在这里插入图片描述

功能介绍:

使用函数确定顺序,对指向的数组的元素进行排序,每个元素的长度以字节为单位。
此函数使用的排序算法通过调用指定的函数(要自己定义元素比较方式函数传给qsort)并将指向元素的指针作为参数来比较元素.
该函数不返回任何值,而是通过按定义重新排序数组元素来修改指向的数组的内容

参数介绍:

参数1(void* base)要排序的数组首地址
参数2(size_t num)数组中的元素个数。
参数3(size_t size)数组中每个元素的大小(以字节为单位)。
参数4 ( int (compar)(const void,const void*))指向数组中元素比较方式的函数指针

二、qsort函数的应用

1.整形数组排序

#include <stdio.h>
#include <stdlib.h>
//注意,由于qsort排序时,并不知道要排序的元素是何种类型,
//所以自定义比较函数的参数都暂时是void*要强制类型转化为对应类型才可以使用.
int int_sort(const void* e1, const void* e2)//自定义整形元素比较方式函数
{
	return  *(int*)e1 - *(int*)e2;
}
int main()
{
	int arr1[10] = { 4,6,1,7,8,2,9,10,3,5 };
	int sz1 = sizeof(arr1) / sizeof(arr1[0]);//计算元素个数
	qsort(arr1, sz1, sizeof(arr1[0]), int_sort);//整形排序
	int i = 0;
	for (i = 0; i < sz1; i++)//整形打印
	{
		printf("%d ", arr1[i]);
	}
	return 0;
}

运行结果:

1 2 3 4 5 6 7 8 9 10

2.浮点型数组排序

//浮点型数组排序
#include <stdio.h>
#include <stdlib.h>
int double_sort(const void* e1, const void* e2)//浮点型比较
{
//注意要强制转化为相对于的类型,然后解引用比较.
	int ret = 0;
	if ((*(double*)e1) - (*(double*)e2) > 0)
	{
		ret = 1;//前面的数比后面大时返回整数
	}
	else ret = -1;//后面数大返回负数;
	return ret;//两个数相等返回0;
}
int main()
{
	double arr2[6] = {3.41, 9.45,	4.78,	3.67,	2.9,	7.36 };
	int sz2 = sizeof(arr2) / sizeof(arr2[0]);//计算数组元素个数
	qsort(arr2, sz2, sizeof(arr2[0]), double_sort);
	int i = 0;
	for (i = 0; i < sz2; i++)//浮点型数组打印
	{
		printf("%5.2lf ", arr2[i]);
	}
	return 0;
}

运行结果:

2.90 3.41 3.67 4.78 7.36 9.45

3.字符型排序

//字符型数组排序
#include <stdio.h>
#include <stdlib.h>
int char_sort(const void* e1, const void* e2)//字符型比较
{
	return (*(char*)e1) - (*(char*)e2);
}
int main()
{
	char arr3[10] = { 'd','g','b','a','e','i','h','c','j','f' };
	int sz3 = sizeof(arr3) / sizeof(arr3[0]);//计算元素个数
	qsort(arr3, sz3, sizeof(arr3[0]), char_sort);
	int i = 0;
		for (i = 0; i < sz3; i++)//字符型打印
	{
		printf("%c ", arr3[i]);
	}
}

运行结果:

a b c d e f g h i j

4.结构体数组排序

strcmp函数用于比较字符串的,它的比较方式是比较字符的ASCII码值,并不是长度,后续在库函数模拟篇会讲到.

//结构体排序
#include <stdio.h>
#include <stdlib.h>
struct student//创建结构体类型
{
	char name[15];
	char sex[3];
	int age;
	float stature;
};
typedef struct student sc;//对结构体类型重命名
int sort_age(const void* e1, const void* e2)//按年龄排序
{

	return (((sc*)e1)->age - ((sc*)e2)->age);
}
int sort_name(const void* e1, const void* e2)//按姓名排序
{
	return strcmp(((sc*)e1)->name, ((sc*)e2)->name);
}
int main()
{
		sc arr4[5] = { {"chu jie niu","男",20,1.73f},
				{"xiao wang","男",19,1.68f},
				{"qing niao","女",21,1.59f},
				{"wao shu li","男",16,1.83f},
			{"peng hu wan","男",15,1.81f} };
		int sz4 = sizeof(arr4) / sizeof(arr4[0]);
		//qsort(arr4, sz4, sizeof(arr4[0]), sort_age);
		qsort(arr4, sz4, sizeof(arr4[0]), sort_name);
		int i = 0;
		printf("姓名	    性别   年龄   身高\n");
		for (i = 0; i < sz4; i++)
		{
			printf("%-12s %-5s %-5d %-5.2fm\n", arr4[i].name, arr4[i].sex, arr4[i].age, arr4[i].stature);
		}
		return 0;
}

运行结果:

姓名        性别   年龄   身高
chu jie niu  男    20    1.73 m
peng hu wan  男    15    1.81 m
qing niao    女    21    1.59 m
wao shu li   男    16    1.83 m
xiao wang    男    19    1.68 m

三、qsort模拟实现(采用冒泡排序模拟)

复习一下冒泡排序吧!

void bubble_sort(int* arr, int sz)//冒泡排序
{
	int i = 0, j = 0;
	for (i = 0; i < sz - 1; i++)
	{
		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;
			}
		}
	}
}
int main()
{
	int arr[10] = { 4,7,1,8,2,3,9,10,5,6 };
	int sz = sizeof(arr) / sizeof(arr[0]);//计算元素个数
	bubble_sort(arr, sz);
	for (int i = 0; i < sz; i++)//数组打印
	{
		printf("%d ",arr[i]);
	}
	return 0;
}

qsort模拟实现(采用冒泡排序模拟实现)

第一步:冒泡函数的参数

首先,要修改的是冒泡排序函数的参数.

void bubble_sort(void * arr, size_t num, size_t width, int (cmp)(const void, const void*))

这四个参数的含义上面介绍qsort参数时有介绍.
需要注意的是,qsort函数事先并不知道要传过来的数组是何种类型,所以先用void*接收.

补充知识:

void*可以接收任何类型的变量,但是并不能直接使用,要强制类型转化为对应类型使用.

第二步:比较元素的的方法

if (arr[j] > arr[j + 1])
语句中的arr[j]arr[j+1]有两点需要注意.
由于事先不知道类型
1.要先将arr强制类型转化为char*,因为一个字节是类型的最小单位,这时width就发挥作用了.

arr[j]转化为 (char*)arr + j * width

arr[j+1]转化为 (char*)arr + (j + 1) * width

在这里插入图片描述
2.元素的比较方式不再是单一的相减就可以,这里就用到了自定义函数,元素的比较方式函数.

if (cmp((char*)arr + j * width, (char*)arr + (j + 1) * width) > 0)

第三步:交换函数

对于这样只能实现整形的交换方式,肯定是不行的.

int tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;

修改为:用char*类型修改交换

swap(char* e1, char* e2, size_t sz)//交换函数
{
	//由于qsort函数事先不知道要比较的元素是何种类型,所以用最小单位一个字节来交换.
	//sz代表元素的所占字节大小
	int i = 0;
	char p = 0;
	for (i = 0; i < sz; i++)
	{
		p = *(e1 + i);
		*(e1 + i) = *(e2 + i);
		*(e2 + i) = p;
	}
}

最后展示全部代码:

#include <stdio.h>
#include <stdlib.h>
struct student//创建结构体类型
{
	char name[15];
	char sex[3];
	int age;
	float stature;
};
typedef struct student sc;//对结构体类型重命名
int sort_age(const void* e1, const void* e2)//按年龄排序
{

	return (((sc*)e1)->age - ((sc*)e2)->age);
}
int sort_name(const void* e1, const void* e2)//按姓名排序
{
	return strcmp(((sc*)e1)->name, ((sc*)e2)->name);
}
int int_sort(const void* e1, const void* e2)//整形比较
{
	return  *(int*)e1 - *(int*)e2;
}
swap(char* e1, char* e2, size_t sz)//交换函数
{
	//由于qsort函数事先不知道要比较的元素是何种类型,所以用最小单位一个字节来交换.
	//sz代表元素的所占字节大小
	int i = 0;
	char p = 0;
	for (i = 0; i < sz; i++)
	{
		p = *(e1 + i);
		*(e1 + i) = *(e2 + i);
		*(e2 + i) = p;
	}
}
//最后一个参数是函数指针,指向两个元素的比较方法这个函数
void bubble_sort(void * arr, size_t num, size_t width, int (*cmp)(const void*, const void*))
{

	int i = 0, j = 0;
	for (i = 0; i < num-1; i++)
	{
		for (j = 0; j < num - 1 - i; j++)
		{
			if (cmp((char*)arr + j * width, (char*)arr + (j + 1) * width) > 0)
			{
				swap((char*)arr + j * width , (char*)arr + (j + 1) * width,width);
			}
		}
	}
}

int main()
{
	int arr[10] = { 4,7,1,8,2,3,9,10,5,6 };
	int sz = sizeof(arr) / sizeof(arr[0]);//计算元素个数
	bubble_sort(arr,sz,sizeof(arr[0]),int_sort);
	for (int i = 0; i < sz; i++)//数组打印
	{
		printf("%d ",arr[i]);
	}
	printf("\n");
	sc arr4[5] = { {"chu jie niu","男",20,1.73f},
		{"xiao wang","男",19,1.68f},
		{"qing niao","女",21,1.59f},
		{"wao shu li","男",16,1.83f},
	{"peng hu wan","男",15,1.81f} };
	int sz4 = sizeof(arr4) / sizeof(arr4[0]);
	qsort(arr4, sz4, sizeof(arr4[0]), sort_age);
	//qsort(arr4, sz4, sizeof(arr4[0]), sort_name);
	int i = 0;
	printf("姓名	    性别   年龄   身高\n");
	for (i = 0; i < sz4; i++)
	{
		printf("%-12s %-5s %-5d %-5.2fm\n", arr4[i].name, arr4[i].sex, arr4[i].age, arr4[i].stature);
	}
	return 0;
}

运行结果:

1 2 3 4 5 6 7 8 9 10
姓名        性别   年龄   身高
peng hu wan  男    15    1.81 m
wao shu li   男    16    1.83 m
xiao wang    男    19    1.68 m
chu jie niu  男    20    1.73 m
qing niao    女    21    1.59 m

qsort函数冒泡排序的模拟实现,就讲到这里了,如果文章有错误或者不理解的地方,欢迎私信牛牛,互相交流,互相学习.

最后,如果文章对大家有帮助的话,求一波三连吧!
💗💗💗886
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/384314.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Docker之部署Mysql

通过docker对Mysql进行部署。 如果没有部署过docker&#xff0c;看我之前写的目录拉取镜像运行容器开放端口拉取镜像 前往dockerHub官网地址&#xff0c;搜索mysql。 找到要拉取的镜像版本&#xff0c;在tag下找到版本。 拉取mysql镜像&#xff0c;不指定版本数&#xff0c…

04 Android基础--RelativeLayout

04 Android基础--RelativeLayout什么是RelativeLayout&#xff1f;RelativeLayout的常见用法&#xff1a;什么是RelativeLayout&#xff1f; 相对布局&#xff08;RelativeLayout&#xff09;是一种根据父容器和兄弟控件作为参照来确定控件位置的布局方式。 根据父容器定位 在相…

JavaWeb--RequestResponse

Request&Response1 Request和Response的概述2 Request对象2.1 Request继承体系2.2 Request获取请求数据2.2.1 获取请求行数据2.2.2 获取请求头数据2.2.3 获取请求体数据2.2.4 小结2.2.5 获取请求参数的通用方式2.3 IDEA快速创建Servlet2.4 请求参数中文乱码问题2.4.1 POST请…

智能家居Homekit系列一智能通断开关

智能通断器&#xff0c;也叫开关模块&#xff0c;可以非常方便地接入家中原有开关、插座、灯具、电器的线路中&#xff0c;通过手机App或者语音即可控制电路通断&#xff0c;轻松实现原有家居设备的智能化改造。 随着智能家居概念的普及&#xff0c;越来越多的人想将自己的家改…

WebRTC系列分享 | WebRTC视频QoS全局技术栈

概述目前总结出WebRTC用于提升QoS的方法有&#xff1a;NACK、FEC、SVC、JitterBuffer、IDR Request、Pacer、Sender Side BWE、Probe、VFR&#xff08;动态帧率调整策略&#xff09;、AVSync&#xff08;音视频同步&#xff09;、动态分辨率调整。这几种方法在WebRTC架构分布如…

上海亚商投顾:沪指窄幅震荡 ChatGPT概念再度走高

上海亚商投顾前言&#xff1a;无惧大盘涨跌&#xff0c;解密龙虎榜资金&#xff0c;跟踪一线游资和机构资金动向&#xff0c;识别短期热点和强势个股。市场情绪沪指今日窄幅震荡&#xff0c;创业板指低开低走&#xff0c;午后跌幅扩大至1%&#xff0c;宁德时代一度跌近4%。6G概…

【架构师】零基础到精通——微服务治理

博客昵称&#xff1a;架构师Cool 最喜欢的座右铭&#xff1a;一以贯之的努力&#xff0c;不得懈怠的人生。 作者简介&#xff1a;一名Coder&#xff0c;软件设计师/鸿蒙高级工程师认证&#xff0c;在备战高级架构师/系统分析师&#xff0c;欢迎关注小弟&#xff01; 博主小留言…

【java基础】一篇文章彻底搞懂lambda表达式

文章目录lambda表达式是什么lambda表达式的语法函数式接口初次使用深入理解方法引用 :: 用法快速入门不同形式的::情况1 object::instanceMethod情况2 Class::instanceMethod情况3 Class::staticMethod对于 :: 的一些示例及其注意事项构造器引用变量作用域使用外部变量定义内部…

web自动化 基于python+Selenium+PHP+Ftp实现的轻量级web自动化测试框架

1、 开发环境 win7 64 PyCharm 4.0.5 setuptools-29.0.1.zip 下载地址&#xff1a;setuptools-29.0.1.zip_免费高速下载|百度网盘-分享无限制 官方下载地址&#xff1a;setuptools PyPI python 3.3.2 mysql-connector-python-2.1.4-py3.3-win64 下载地址&#xff1a;mysq…

企业 Active Directory 自助服务

您的企业是否正在寻找一个全面的 Active Directory 自助服务解决方案&#xff0c;使用户能够在没有帮助台帮助的情况下满足自己的 Active Directory 需求&#xff1f;ADSelfService Plus 了解您的安全问题&#xff0c;并提供基于审批的自助服务工作流功能&#xff0c;使管理员能…

内网vCenter部署教程一

PS&#xff1a;因为交换机链路为trunk&#xff0c;安装先登录ESXI&#xff0c;将端口组改为管理vlan ID&#xff08;1021&#xff09; 一、双击镜像&#xff0c;打开文件夹&#xff0c;目录为F:\vcsa-ui-installer\win32&#xff0c;双击installer.exe 二、先设置语言为中文 三…

机器学习笔记之狄利克雷过程(三)随机测度的生成过程(折棍子过程)

机器学习笔记之狄利克雷过程——随机测度的生成过程[折棍子过程]引言回顾&#xff1a;狄利克雷过程——定义随机测度的生成过程从随机测度的生成过程观察标签参数α\alphaα与随机测度离散程度之间的关系引言 上一节使用公式推导的方式介绍了狄利克雷过程中标量参数α\alphaα…

云服务器ECS 什么是云服务器ECS?

云服务器ECS&#xff08;Elastic Compute Service&#xff09;是阿里云提供的性能卓越、稳定可靠、弹性扩展的IaaS&#xff08;Infrastructure as a Service&#xff09;级别云计算服务。 云服务器ECS免去了您采购IT硬件的前期准备&#xff0c;让您像使用水、电、天然气等公共…

【线性DP】猴子与香蕉

可恶&#xff0c;就差一点就能独立写出这道题了&#xff01;4548. 猴子和香蕉 - AcWing题库题意&#xff1a;思路&#xff1a;设计状态的时候一开始不知道怎么设&#xff0c;后来试了一下发现这样设很合理因此在设状态的时候很多时候都要试一试当时间或空间吃不消时&#xff0c…

django ModelForm外鍵問題

背景 django在使用ModelForm時如果存在外鍵字段&#xff0c;默認是ChoiceField讓你選擇外鍵關聯表有的值&#xff0c;但是如果關聯表的數據很多的話選擇就很難找到選項。所以想能不能換成輸入框TextInput。 舉個例子 models.py 這裏建了兩個表&#xff0c;把用戶表的name作…

ERP的实施节省了公司人力吗?

业界一直有句老话&#xff1a;“不上ERP等死&#xff0c;上了ERP找死”。 可把ERP的尴尬处境说透了。 有人把ERP奉为信仰&#xff1a;“那些说ERP不好用的根本是没用明白。” 有人则认为ERP只是卖概念&#xff0c;冷嘲&#xff1a;“实施ERP的企业&#xff0c;估计一半都倒闭…

手机质保调到36个月,会对行业造成怎样的冲击?

2月17日&#xff0c;中国信通院发布数据显示&#xff0c;2022年全年国内市场手机出货量累计2.72亿部&#xff0c;同比下降22.6%。其中5G手机的出货量为2.14亿部&#xff0c;同比下降19.6%。这则数据打破了一些手机行业内的美好幻想&#xff1a;5G时代的到来&#xff0c;并没有涌…

哔哩哔哩自动生成视频上传,B站发布软件使用教程

哔哩哔哩自动生成视频上传&#xff0c;B站发布软件使用教程&#xff0c;全自动引流发帖软件介绍#引流发帖软件#全自动引流发帖#引流推广#拓客引流#爆粉软件 大家好&#xff0c;我是百收编辑狂潮老师&#xff0c;下面给大家讲一下 b 站上传软件它的一个使用方法。第一次使用的时…

几种常见的 JVM 调优场景

一、cpu占用过高 cpu占用过高要分情况讨论&#xff0c;是不是业务上在搞活动&#xff0c;突然有大批的流量进来&#xff0c;而且活动结束后cpu占用率就下降了&#xff0c;如果是这种情况其实可以不用太关心&#xff0c;因为请求越多&#xff0c;需要处理的线程数越多&#xff…

[Java·算法·困难]LeetCode25. K 个一组翻转链表

每天一题&#xff0c;防止痴呆题目示例分析思路1题解1分析思路2题解2分析思路3题解3&#x1f449;️ 力扣原文 题目 给你链表的头节点 head &#xff0c;每 k 个节点一组进行翻转&#xff0c;请你返回修改后的链表。 k 是一个正整数&#xff0c;它的值小于或等于链表的长度。…