c语言-库函数qsort()初识

目录

  • 前言
  • 一、qsort()的介绍及使用
    • 1.1 qsort()的介绍
    • 1.2 qsort()的使用
      • 1.2.1 使用qsort|()对整型数组按照升序排序
      • 1.2.2 使用qsort()对整型数组按照降序排序
      • 1.2.3 使用qsort()对结构体数组数据进行排序
  • 二、利用冒泡排序模拟实现对任何数据进行排序
    • 2.1 冒泡排序
    • 2.2 模仿qsort()实现bubble_sort()对任何数据类型的数据排序
      • 2.2.1 代码实现
      • 2.2.2 测试对整型数组排序
      • 2.2.3 测试对结构体数组数据排序
  • 总结


前言

本篇文章介绍库函数qsort()的使用以及利用冒泡排序的思想模拟对任何类型的数据进行排序。


一、qsort()的介绍及使用

1.1 qsort()的介绍

下面是cplusplus对qsort()的叙述,详情https://cplusplus.com/reference/cstdlib/qsort/
在这里插入图片描述
在这里插入图片描述

qsort()可以对任意类型的数据进行排序。
对qsort()参数进行介绍:

void* base:指向需要被排序数组的起始位置。
size_t num:待排序的元素个数
size_t size:待排序的元素的大小(单位:字节)
int (*compar)(const void*, const void*):函数指针,指向比较函数,可以实现自定义比较规则。

1.2 qsort()的使用

1.2.1 使用qsort|()对整型数组按照升序排序

//升序
int compare_asc(const void* e1, const void* e2)
{return (*(int*)e1 - *(int*)e2);
}
int main()
{int arr[] = { 40, 10, 100, 90, 20, 25 };int sz = sizeof(arr) / sizeof(arr[0]);qsort(arr, sz, sizeof(arr[0]), compare_asc);int i = 0;for (i = 0; i < sz; i++)printf("%d ", arr[i]);return 0;
}

1.2.2 使用qsort()对整型数组按照降序排序

//降序
int compare_dec(const void* e1, const void* e2)
{return (*(int*)e2 - *(int*)e1);
}int main()
{int arr[] = { 40, 10, 100, 90, 20, 25 };int sz = sizeof(arr) / sizeof(arr[0]);qsort(arr, sz, sizeof(arr[0]), compare_dec);int i = 0;for (i = 0; i < sz; i++)printf("%d ", arr[i]);return 0;
}

1.2.3 使用qsort()对结构体数组数据进行排序

按照年龄升序排序:

//定义结构体
struct Stu {char name[20];int age;float height;
};//输出结构体数组数据
void print_stu(struct Stu* stu,int sz)
{int i = 0;for (i = 0; i < sz; i++){printf("%s\t%-6d\t%.2f\n", (stu + i)->name, (stu + i)->age, (stu + i)->height);}
}//按照年龄升序进行排序
int compare_stuByAge_asc(const void* e1, const void* e2)
{return (((struct Stu*)e1)->age - ((struct Stu*)e2)->age);
}int main()
{struct Stu student[3] = { {"zhangsan", 18, 170.50f},{"lisi", 20, 185.25f},{"wangwu", 17, 165.55f} };int sz = sizeof(student) / sizeof(student[0]);printf("原顺序\n");print_stu(student, sz);//按照年龄升序排序qsort(student, sz, sizeof(student[0]), compare_stuByAge_asc);printf("按照年龄升序\n");print_stu(student, sz);return 0;
}

二、利用冒泡排序模拟实现对任何数据进行排序

2.1 冒泡排序

void bubble_sort(int arr[], int sz)
{int i = 0;int flag = 1;//假设数据有序//排序趟数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;flag = 0;}}//当进行第一趟排序时,flag未改变,说明没有进行交换,数组有序if (1 == flag){break;}}
}int main()
{int arr[] = { 40, 10, 100, 90, 20, 25 };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;
}

对比qsort()发现,bubble_sort()只能对整型数组数据进行排序,为了增加bubble_sort()的通用性,可以模仿qsort()的写法实现bubble_sort()对任何数据类型的排序。

2.2 模仿qsort()实现bubble_sort()对任何数据类型的数据排序

2.2.1 代码实现

//每次交换一个字节的内容
//循环交换width个字节的内容
void Swap(char* e1, char* e2, int width)
{char tmp = 0;int i = 0;for(i = 0; i < width; i++){ tmp = *e1;*e1 = *e2;*e2 = tmp;e1++;e2++;}
}void bubble_sort(void* base, int sz,int width, int(*compare)(const void* e1, const void* e2))
{int i = 0;int flag = 1;//假设数据有序//排序趟数for (i = 0; i < sz - 1; i++){int j = 0;//每趟要比较数据的个数for (j = 0; j < sz - 1 - i; j++){//利用compare()回调函数, >0进行交换if (compare((char*)base+j*width, (char*)base+(j+1)*width) > 0){//交换Swap((char*)base + j * width, (char*)base + (j + 1) * width,width);flag = 0;}}//当进行第一趟排序时,flag未改变,说明没有进行交换,数组有序if (1 == flag){break;}}
}

compare((char*)base+j*width, (char*)base+(j+1)*width) > 0;
返回值有三个
返回值为 =0,说明e1和e2指向的数据值相等
返回值为<0,有两种情况:

  1. e1指向的数据值小于e2指向的数据值
  2. e1指向的数据值大于e2指向的数据值

返回值为>0,有两种情况

  1. e1指向的数据值小于e2指向的数据值
  2. e1指向的数据值大于e2指向的数据值

为什么出现两种情况?
原因:因为compare()的返回值是两个值相减,但无法确定哪个是减数
升序和降序的控制
升序:当e1指向的数据值作为被减数时,即e1-e2
降序:当e2指向的数据值作为被减数时,即e2-e1。
注意:e1-e2只是作为说明,具体怎么比较,由自定义实现比较规则。(具体看例子)
为什么选择compare((char*)base+j*width, (char*)base+(j+1)width) > 0作为判断交换的条件?
因为默认把e1-e2作为升序,即从小到大排序。
如果把compare((char
)base+j*width, (char*)base+(j+1)width) > 0
换成compare((char
)base+j*width, (char*)base+(j+1)*width) < 0
那么默认e1-e2是降序,即从大到小排序。

	(char*)base + j * width //指向要比较的第一个元素(char*)base + (j + 1) * width //指向要比较的第二个元素//利用(char*)base强制类型转换,分别指向被比较元素的起始位置

在这里插入图片描述

图2.2.1
	void Swap(char* e1, char* e2, int width);

实现的是交换每个字节的内容,width是每个元素的大小。由于是char*类型的指针,所以一次交换只能交换一个字节的内容,为了能够交换整个元素的内容,所以需要交换width次。

2.2.2 测试对整型数组排序

//对数组进行升序
int compare_int_asc(const void* e1, const void* e2)
{return (*(int*)e1 - *(int*)e2);
}//降序
int compare_int_dec(const void* e1, const void* e2)
{return (*(int*)e2 - *(int*)e1);
}int main()
{int arr[] = { 40, 10, 100, 90, 20, 25 };int sz = sizeof(arr) / sizeof(arr[0]);bubble_sort(arr, sz, sizeof(arr[0]),compare_int_dec);int i = 0;for (i = 0; i < sz; i++)printf("%d ", arr[i]);return 0;
}

2.2.3 测试对结构体数组数据排序

//定义结构体
struct Stu {char name[20];int age;float height;
};//输出结构体数据
void print_stu(struct Stu* stu,int sz)
{int i = 0;for (i = 0; i < sz; i++){printf("%s\t%-6d\t%.2f\n", (stu + i)->name, (stu + i)->age, (stu + i)->height);}
}
//按照年龄升序进行排序
int compare_stuByAge_asc(const void* e1, const void* e2)
{return (((struct Stu*)e1)->age - ((struct Stu*)e2)->age);
}//按照名字的字母序排序
int compare_stuByName(const void* e1, const void* e2)
{return strcmp(((struct Stu*)e1)->name, ((struct Stu*)e2)->name);
}int main()
{struct Stu student[3] = { {"zhangsan", 18, 170.50f},{"lisi", 20, 185.25f},{"wangwu", 17, 165.55f} };int sz = sizeof(student) / sizeof(student[0]);printf("原顺序\n");print_stu(student, sz);//按照年龄升序排序//bubble_sort(student, sz, sizeof(student[0]), compare_stuByAge_asc);//按照名字字母序bubble_sort(student, sz, sizeof(student[0]), compare_stuByName);//printf("按照年龄升序\n");printf("按照名字字母序\n");print_stu(student, sz);return 0;
}

总结

本篇文章介绍了库函数qsort()的使用,以及模仿qsort(),利用冒泡排序模拟实现对任何数据类型的数据进行排序。

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

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

相关文章

【REST2SQL】04 REST2SQL第一版Oracle版实现

【REST2SQL】01RDB关系型数据库REST初设计 【REST2SQL】02 GO连接Oracle数据库 【REST2SQL】03 GO读取JSON文件 REST2SQL的第一个版本&#xff0c;只支持Oracle数据库&#xff0c;以后会逐步加入其它数据看的支持。 项目文件组织如下&#xff1a; 1 REST2SQL为项目主目录 …

leetcode动态规划问题总结 Python

目录 一、基础理论 二、例题 1. 青蛙跳台阶 2. 解密数字 3. 最长不含重复字符的子字符串 4. 连续子数组的最大和 5. 最长递增子序列 6. 最长回文字符串 7. 机器人路径条数 8. 礼物的最大价值 一、基础理论 动态规划其实是一种空间换时间的基于历史数据的递推算法&…

linux常见操作,and一些练习题加线上练习网站,无须配置linux.持续更新中。。。。

文章目录 cd命令相对路径特殊的路径表达符和cd一起使用pwdmore 查看文件内容支持翻页小技巧clear用户&#xff0c;用户权限 and 用户的切换如何创建用户 ls和通配符的使用利用通配符 *grep 过滤管道符 |如何学习Linux在线练习网站 https://www.lanqiao.cn/courses/1 cd命令 cd…

Basal前端梳理

Basalt前端逻辑梳理 TBB安装参考 https://zhuanlan.zhihu.com/p/480823197 代码注释参考 https://blog.csdn.net/qq_39266065/article/details/106175701#t7 光流追踪参考 https://blog.csdn.net/weixin_41738773/article/details/130282527 VI Odometry KLT tracking 原理 …

第九届中西部外语翻译大赛初赛阶段已经圆满结束

2023年第九届中西部外语翻译大赛&#xff08;以下简称竞赛&#xff09;&#xff0c;于2023年12月30日至31日举行。历届中西部外语翻译大赛均由中西部翻译协会共同体指导发起&#xff0c;各省市译协共建学术指导委员会&#xff0c;获奖证书盖章单位由四川省翻译协会、广西翻译协…

c# 学习笔记 - 集合(List)

文章目录 1.概论1.1 List 特性1.2 .NET API 2. 基本使用2.1 样例 3. 添加类操作3.1 Insert() 4. 删除类操作4.1 Remove()4.2 RemoveAt() 5. 查找类操作6. 排序类操作6.1 Sort(Comparsion<T>) 7. 其他类操作 1.概论 1.1 List 特性 可通过索引访问的强类型列表&#xff0c…

STM32学习笔记二十二:WS2812制作像素游戏屏-飞行射击游戏(12)总结

至此&#xff0c;飞行射击游戏已经基本实现该有的功能&#xff0c;已经比较接近早期的商业游戏了。 如果采用脚本&#xff0c;可以完成关卡游戏&#xff0c;如果不用&#xff0c;也可以做成无限挑战游戏。 我们汇总一下制作的过程&#xff1a; 1、建模UML 2、主循环处理过程…

设计模式篇章(1)——理论基础

设计模式&#xff1a;在软件开发中会面临许多不断重复发生的问题&#xff0c;这些问题可能是代码冗余、反复修改旧代码、重写以前的代码、在旧代码上不断堆新的代码&#xff08;俗称屎山&#xff09;等难以扩展、不好维护的问题。因此1990年有四位大佬&#xff08;GoF组合&…

3的幂00

题目链接 3的幂 题目描述 注意点 无 解答思路 不断除以3直到除数或余数为0为止&#xff0c;判断除完后的数字是否为1 代码 class Solution {public boolean isPowerOfThree(int n) {while (n / 3 ! 0) {if (n % 3 ! 0) {return false;}n n / 3;}return n 1;} }关键点 …

对称加密技术有哪些类型

对称加密是一种加密方式&#xff0c;其加密和解密所使用的密钥是相同的。这种方式的特点是速度快&#xff0c;效率高&#xff0c;适合用于大量数据的加密和解密。对称加密算法有很多种&#xff0c;常见的有AES、DES、3DES等。 对称加密的应用场景非常广泛&#xff0c;下面是一些…

Linux下配置静态ip地址

问题&#xff1a;虚拟机重启后ip地址动态更新&#xff0c;导致连shell十分麻烦 解决&#xff1a; 1. 进入配置文件 vi /etc/sysconfig/network-scripts/ifcfg-ens33 2.1 修改配置 BOOTPROTOstatic ONBOOTyes2.2 新增配置 #ip地址(自定义) IPADDR192.168.149.131 #子网掩码 …

2023年12月 C/C++(四级)真题解析#中国电子学会#全国青少年软件编程等级考试

C/C++编程(1~8级)全部真题・点这里 第1题:移动路线 桌子上有一个m行n列的方格矩阵,将每个方格用坐标表示,行坐标从下到上依次递增,列坐标从左至右依次递增,左下角方格的坐标为(1,1),则右上角方格的坐标为(m,n)。 小明是个调皮的孩子,一天他捉来一只蚂蚁,不小心把蚂蚁…

一款开源的MES系统

随着工业4.0的快速发展&#xff0c;制造执行系统&#xff08;MES&#xff09;成为了智能制造的核心。今天&#xff0c;将为大家推荐一款开源的MES系统——iMES工厂管家。 什么是iMES工厂管家 iMES工厂管家是一款专为中小型制造企业打造的开源MES系统。它具备高度的可定制性和灵…

[论文笔记] Qwen-7B tokenizer

https://github.com/QwenLM/Qwen/blob/main/tokenization_note_zh.md#%E6%99%AE%E9%80%9Atoken https://huggingface.co/Qwen/Qwen-7B 一、Qwen-7B 介绍 Qwen-7B采用UTF-8字节级别的BPE tokenization方式,并依赖tiktoken这一高效的软件包执行分词。 Qwen-7B中有两类token,即…

Selenium教程:级联选择+日期框+弹框,组件的示例练习

1.Cascader级联选择&#xff0c;通常指的是在多个层级或类别中进行选择&#xff0c;每个层级或类别的选择依赖于前一个层级或类别的选择结果。常用于省市区、公司级层、事务分类等。 网页元素结构 实现代码 # Author : 小红牛 # 微信公众号&#xff1a;WdPython from time i…

ROS-urdf集成gazebo

文章目录 一、URDF与Gazebo基本集成流程二、URDF集成Gazebo相关设置三、URDF集成Gazebo实操四、Gazebo仿真环境搭建 一、URDF与Gazebo基本集成流程 1.创建功能包 创建新功能包&#xff0c;导入依赖包: urdf、xacro、gazebo_ros、gazebo_ros_control、gazebo_plugins 2.编写URD…

HarmonyOS状态管理概述

状态管理概述 在前文的描述中&#xff0c;我们构建的页面多为静态界面。如果希望构建一个动态的、有交互的界面&#xff0c;就需要引入“状态”的概念。 图1 效果图 上面的示例中&#xff0c;用户与应用程序的交互触发了文本状态变更&#xff0c;状态变更引起了UI渲染&…

C#实现个人账本管理系统

git地址&#xff1a;https://gitee.com/myshort-term/personal-ledger-management-system 1.系统简介 LedgerManagementSystem是一个小型的个人账本管理系统&#xff0c;可对收支项目进行增加、删除、修改、查询以及导入和导出。可对每日的各类收支项目进行汇总并查看和修改收…

STM32 基础知识(探索者开发板)--146讲 IIC

IIC特点&#xff1a; 同步串行半双工通信总线 IIC有一个弱上拉电阻&#xff0c;在主机和从机都没有传输数据下拉时&#xff0c;总线会自动上拉 SCL在低电平期间&#xff0c;改变SDA的值来上传数据&#xff0c;方便SCL电平上升时进行数据读取 SCL在高电平期间&#xff0c;不能…