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.mfbz.cn/a/301502.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

BurpSuite信息收集篇

BurpSuite信息收集篇 1.填充目标站点地图2.使用 Burp Suite 自动发现内容3.使用 Burp Suite 枚举子域1.填充目标站点地图 演示站点 ginandjuice.shop 1、抓取目标的请求包 2、在不关闭浏览器的情况下,转到目标>站点地图。请注意,已自动添加一个节点来表示目标域 3、右键…

【EasyExcel】导出excel冻结表头和冻结指定列并支持筛选器

需求背景&#xff1a; 导出excel的同时冻结表头和前两列基础信息&#xff0c;方便导出后用户查看信息。 一、技术选型&#xff1a; easyExcel的自定义写策略处理&#xff1a;SheetWriteHandler 二、方案设计&#xff1a;&#xff08;基于实现 SheetWriteHandler 接口&#xf…

RabbitMQ(九)死信队列

目录 一、简介1.1 定义1.2 何时进入死信队列&#xff1f;1.3 死信消息的变化1.4 死信队列的应用场景1.5 死信消息的生命周期 二、代码实现2.1 死信队列的配置步骤2.2 配置类2.3 配置文件2.4 生产者2.5 业务消费者2.6 死信消费者2.7 测试结果 三、总结 RabbitMQ 是流行的开源消息…

【EI会议征稿通知】第三届城市规划与区域经济国际学术会议(UPRE 2024)

第三届城市规划与区域经济国际学术会议&#xff08;UPRE 2024&#xff09; 2024 3rd International Conference on Urban Planning and Regional Economy 第三届城市规划与区域经济国际学术会议&#xff08;UPRE 2024&#xff09;于2024年4月19-21日在泰国曼谷举行。会议旨在…

Qt/QML编程学习之心得:Linux下读写文件File(24)

在Linux嵌入式系统中,经常会使用Qt来读写一个文件,判断一个文件是否存在,具体如何实现呢? 首先,要使用linux系统中相关的头文件: #include <unistd.h> #include <stdio.h> #include <stdlib.h> 其次,判断路径是否存在, if(!dir.exists()){mkdir(…

智能驾驶打响“进阶战”:高、中、低阶赛道如何突围?

伴随智能驾驶普及进入新周期&#xff0c;高、中、低阶市场呈现不同的突围方式。 根据高工智能汽车研究院监测数据&#xff0c;2023年1-9月&#xff0c;中国市场&#xff08;不含进出口&#xff09;乘用车新车销售标配搭载L2&#xff08;含L2&#xff09;的渗透率达到36.31%&am…

QT常用控件使用及布局

QT常用控件使用及布局 文章目录 QT常用控件使用及布局1、创建带Ui的工程2、ui界面介绍1、界面设计区2、对象监视区3、对象监属性编辑区4、信号与槽5、布局器6、控件1、Layouts1、布局管理器2、布局的dome 2、Spacers3、Buttons4、项目视图组(Item Views)5、项目控件组(Item Wid…

【sgPasswordInput】自定义组件:带前端校验密码强度的密码输入框,能够提供密码强度颜色提示和文字提示

特性&#xff1a; 有密码强度颜色提示密码强度进度条提示支持设置默认输入提示和密码长度 sgPasswordInput源码 <template><div :class"$options.name" style"width: 100%"><el-inputstyle"width: 100%"ref"psw"type&…

软件使用手册

一简介 软件分两部分&#xff0c;股票监测程序&#xff0c;监测列表配置数据页面以及手机端接收监控数据。股票监测程序需要在电脑上运行。下载地址为程序下载地址。监控股票配置页面地址为动态列表。 二使用介绍 2.1监控客户端 2.1.1程序安装及登录 下载安装exe程序程序下载地…

C#开源的一款友好的.NET SDK管理器

前言 今天推荐一款由C#开源的、友好的.NET SDK管理器&#xff1a;Dots。 工具介绍 Dots 是一款 .NET SDK 管理器&#xff0c;可让您轻松安装、卸载和切换 .NET SDK。它是一款跨平台工具&#xff0c;可在 Windows 和 macOS 上运行&#xff0c;即将支持 Linux。它由 C# 编写&a…

部署可道云网盘的一个漏洞解决

目录 1漏洞展示 2.防范措施 1漏洞展示 因为可道云网盘的上传文档有保存在 /data/Group/public/home/文档/ 中,当别有用心之人知道个人部署的域名与上次的文件后&#xff0c;可以进行访问拿到uid。例我在我部署的网盘上上次一个aa.php 文件&#xff0c;然后拿来演示 然后通过…

Axure RP Extension For Chrome 插件安装

1. 下载好 AXURE RP EXTENSION For Chrome 插件之后解压成文件夹 2. 打开浏览器&#xff0c;找到设置--更多工具--扩展程序--加载已加压的扩展程序&#xff0c;选择解压好的文件夹 3. 点击详细信息&#xff0c;打开访问网址权限

静态路由、代理ARP

目录 静态路由静态路由指明下一跳和指明端口的区别代理ARP 我们知道&#xff0c;跨网络通信需要路由 路由有三种类型&#xff1a; 1.直连路由。 自动产生的路由&#xff0c;当网络设备连接到同一网络时&#xff0c;他们可以自动学习到对方的存在。自动学习相邻网络设备的直连信…

C/C++ 联合体

目录 联合体概述 联合体的内存分配 联合体大小计算 联合体概述 联合与结构非常的相似&#xff0c;主要区别就在于联合这两个字。 联合的特征&#xff1a;联合体所包含的成员变量使用的是同一块空间。 联合体定义 //联合类型的声明 union Un {char c;int i; }; //联合变量…

PAT 乙级 1049 数列的片段和

分数 20 作者 CAO, Peng 单位 Google 给定一个正数数列&#xff0c;我们可以从中截取任意的连续的几个数&#xff0c;称为片段。例如&#xff0c;给定数列 { 0.1, 0.2, 0.3, 0.4 }&#xff0c;我们有 (0.1) (0.1, 0.2) (0.1, 0.2, 0.3) (0.1, 0.2, 0.3, 0.4) (0.2) (0.2, 0.3) …

VSD Viewer for Mac Visio绘图文件阅读器

Visio Viewer for Mac是一款专为Mac用户设计的Visio文件查看工具。它允许用户在Mac上查看和共享Visio文件&#xff0c;无需安装微软的Visio软件。这对于那些没有购买或没有访问Windows操作系统的Mac用户来说&#xff0c;是一个非常方便的选择。 该软件支持Visio的各种文件格式…

五行能量,影响着你的运势,莫小看!

五行的能量不能小看&#xff0c;时时刻刻在影响着我们。五行为聚之成形&#xff0c;散之成气&#xff1b;五行学说讲的是能量与气场&#xff0c;它指出世界有五种元素&#xff1a;金、水、木、火、土&#xff0c;这代表世界的五种不同的能量。五行能量存在于我们的身边&#xf…

分析抖音直播弹幕评论和礼物的websocket数据流信息,通过proto协议解析消息内容思路

现在定位到一个解析的大概位置&#xff1a; e.decode function(e, t) {e instanceof o || (e o.create(e));for (var n, i, s void 0 t ? e.len : e.pos t, u new r.webcast.im.MemberMessage(r.webcast. 通过请求找到发送请求的js代码位置&#xff0c;然后通过跟踪这…

Halcon机器视觉和运动控制软件通用框架,24年1月最新版新增UI设计器,插件式开发,开箱即用 仅供学习!

24年1月更新 下载点我 此版本已经添加ui设计器。具体功能如上所示&#xff0c;可以自定义变量&#xff0c;写c#脚本&#xff0c;自定义流程&#xff0c;包含了halcon脚本和封装的算子&#xff0c;可自定义ui&#xff0c;通过插件形式开发很方便拓展自己的功能。 ui设计器

Web前端-JavaScript(BOM)

文章目录 1.1 常用的键盘事件1.1.1 键盘事件1.1.2 键盘事件对象1.1.3 案例一 1.2 BOM1.2.1 什么是BOM1.2.2 BOM的构成1.2.3 window1.2.4 window对象常见事件窗口/页面加载事件**第1种****第2种** 调整窗口大小事件 1.2.5 定时器setTimeout() 炸弹定时器停止定时器**案例&#x…
最新文章