qsort的使用与实现

 c语言常见的排序方法大概有这些,今天我们所讲的是就是qsort快排的讲解

 头文件

 qsort的使用

 我们先使用msdn查看他的相关资料,得知这个函数的传参请情况

 1.void *base

 翻译过来就是将要排序的函数的起始位置/数组首元素地址

2.size_t num 

 翻译过来就是数组个数(要注意这里的个数是指该数组元素的个数,单位是个)

3.size_t width 

 翻译过来就是每个元素大小(以字节计)

4. int (__cdecl *compare )(const void *elem1, const void *elem2 )

最后一个参数看起来很长,但实际看起来,他就是一个函数指针 ,我们看看在msdn上他的解释是什么

 compare                       elem1                                     elem2

[数] 比较函数              指向搜索键的指针                指向要与键进行比较的数组元素的指针

 经过阅读以上文章得知,compare函数的作用便是

compare( (void *) elem1, (void *) elem2 );

所以我们便不难实现compare函数 

返回类型为int   两个形参全都是void*

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

以上就是通过msdn查阅资料得知其功能,从而得知其的使用方法

以下排序展示效果

#include <stdio.h>
#include <stdlib.h>
int compare(const void* e1, const void* e2)
{
	return (*(int*)e1 - *(int*)e2);
}
int main()
{
	int arr[10] = { 8,5,2,3,6,4,1,7,9,0 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	qsort(arr, sz, sizeof(arr[0]),compare);
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

代码运行起来便是如此效果

当然降序只需要将第四个参数的逻辑该反,具体就是如下

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

qsort排序结构体

上文的使用只在整形数组内使用了,但如果是结构体的话使用会不会又不同呢?

我们带着这个疑问,对上文的代码进行改进,使其可以对结构体排序;

#include <stdio.h>
#include<stdlib.h>
struct stu
{
	char name[20];
	int age;
	char sex[5];
};
int compare(const void* e1, const void* e2)
{
	return (*(int*)e1 - *(int*)e2);
}
int main()
{
	struct stu s[3] = { {"李四",20,"男"},{"王五",20,"男"} ,{"赵四",20,"男"} };
	int sz = sizeof(s) / sizeof(s[0]);
	qsort(s, sz, sizeof(s[0]),compare);
	int i = 0; 
	for (i = 0; i < sz; i++)
	{
		printf("%s %d %s\n", s[i].name, s[i].age, s[i].sex);
	}
	return 0;
}

貌似也是可以行的通的,但是思考过后,发现我们是以什么方式排序的呢?我们没有修改第四个形参的函数的内部修改,第四个形参的作用就意在说明我们是利用什么方式在排序,(结构体以名字排序)那么我们就对于不同的类型要使用不同的compare,

以下代码 便是compare 通过name

#include<string.h>
int com_name(const void* e1, const void* e2)
{
	return (strcmp(((struct stu*)e1)->name, ((struct stu*)e2)->name));
}//这里一定要记得强制类型转换

qsort的实现(排序整形)

 qsort我们会用以后,那么就要去尝试着怎么自己实现,

我们先看以下冒泡排序的实现方法

void Bubble_sort(int arr[], int size)//int arr[]等价于int *arr
{
	int j, i;
	for (i = 0; i < size - 1; i++)//size-1是因为不用与自己比较,所以比的数就少一个
	{
		int count = 0;
		for (j = 0; j < size - 1 - i; j++)	//size-1-i是因为每一趟就会少一个数比较
		{
			if (arr[j] > arr[j + 1])//这是升序排法,前一个数和后一个数比较,如果前数大则与后一个数换位置
			{
				int tem = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tem;
				count = 1;

			}
		}
		if (count == 0)			//如果某一趟没有交换位置,则说明已经排好序,直接退出循环
			break;
	}
}
int main()
{
	int arr[10] = { 9,8,7,6,5,4,3,2,1,0 };
	int i = 0;
	Bubble_sort(arr, 10);
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

 所标红的地方便是相当于qsort里面第四个参数(比较),我们在冒泡排序实现代码基础上进行修改

对于实现者:不知道排序的是什么类型的数组
对于使用者:知道其排序的是什么类型的数组
所以使用去qsort最重要的是对于不同类型使用的com(第四个参数)是不同的

对于第一个参数

msdn上是void*类型的,void*类型的好处就是可以接受任何类型的地址,利用这一点就可以排序任何类型的数组

对于第二个参数跟冒泡排序的参数sz一样,第三个参数与第一个参数结合,不就是解释了每个元素大小(把第一个参数强制类型转化为char*)(也大致就了解是什么类型)达到了冒泡排序第一个参数作用

修改参数:

void Bubble_sort(void* base, 
	size_t num, 
	size_t width, 
	int (*com)(const void* e1, const void* e2)
)

大致思路路就是

 com(比较大小)

 

if (com((char*)base + j * width, (char*)base + (j + 1) * width)>0)

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

swap(交换)

 

swap((char*)base + j * width, (char*)base + (j + 1) * width, width);

void swap(char* buf1, char* buf2, int width)
{
	int i = 0;
	for (i = 0; i < width; i++)
	{
		char tmp = *buf1;
		*buf1 = *buf2;
		*buf2 = tmp;
		buf1++, buf2++;
	}
}

总结

 

#include<stdio.h>
void swap(char* buf1, char* buf2, int width)
{
	int i = 0;
	for (i = 0; i < width; i++)
	{
		char tmp = *buf1;
		*buf1 = *buf2;
		*buf2 = tmp;
		buf1++, buf2++;
	}
}
int com(const void* e1, const void* e2)
{
	return *(int*)e1 - *(int*)e2;
}
void Bubble_sort(void* base,size_t num,size_t width,int (*com)(const void* e1, const void* e2))
{
	int j, i;
	for (i = 0; i < num - 1; i++)
	{
		int count = 0;
		for (j = 0; j < num - 1 - i; j++)
		{
			if (com((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[10] = { 9,8,7,6,5,4,3,2,1,0 };
	int i = 0;
	int sz = sizeof(arr) / sizeof(arr[0]);
	Bubble_sort(arr, sz, sizeof(arr[0]), com);
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

 

 排序结构体的数组只需要改变com函数即可

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

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

相关文章

vue项目获取拼音首字母

工具包 pinyin-pro npm install pinyin-pro 官方地址 pinyin-pro | pinyin-pro性能优异、转换准确的 js 中文转拼音工具https://pinyin-pro.cn/示例代码(获取每个汉字的拼音首字母) import {pinyin} from pinyin-pro;function getPinyinInitial(name){if (name) {let py p…

redis实战笔记汇总

文章目录 1 NoSQL入门概述1.1 能干嘛&#xff1f;1.2 传统RDBMS VS NOSQL1.3 NoSQL数据库的四大分类1.4 分布式数据库CAP原理 BASE原则1.5 分布式集群简介1.6 淘宝商品信息的存储方案 2 Redis入门概述2.1 是什么&#xff1f;2.2 能干嘛&#xff1f;2.3 怎么玩&#xff1f;核心…

高性能MySQL 第4版

第一章MySQL架构 MySQL提供了多种锁的颗粒度&#xff0c;每种MySQL存储引擎都可以实现自己的锁策略和锁力度。 行级锁是在存储引擎而不是在服务器中实现的。 隔离界别 READ UNCOMMITTED - 脏读 在事务中可以可以查看到其他事务中还没有提交的修改。实际中很少用。 READ C…

运筹学_1.1.4 线性规划问题-解的概念

1.1.4 线性规划问题-解的概念 一、可行解与最优解二、基的概念三、基变量、基向量&#xff1b;非基变量、非基向量&#xff1b;基解、基可行解&#xff1b;四、最优解与可行解、基可行解的关系五、用例题&#xff08;枚举法&#xff09;巩固基解、基可行解、最优解三个概念1、例…

鸿蒙Harmony应用开发—ArkTS声明式开发(点击事件)

组件被点击时触发的事件。 说明&#xff1a; 从API Version 7开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 onClick onClick(event: (event: ClickEvent) > void) 点击动作触发该回调。 卡片能力&#xff1a; 从API version 9开始…

【python】`assert`断言语句

assert是一个断言语句&#xff0c;用于在代码中检查某个条件是否为真。 如果条件为假&#xff0c;将触发AssertionError 异常&#xff0c;从而指示存在错误。

【博图TIA-Api】通过Excel自动新建文件夹和导入FB块

【博图TIA-Api】通过Excel自动新建文件夹和导入FB块 说明思路准备获取Excel表格内文件名和FB块名等信息新建文件夹部分筛分获取的文件夹数据&#xff0c;去掉重复内容创建文件夹 导入FB块导出FB块的xml文件查找需要放置的文件夹导入块 说明 续上一篇文章&#xff0c;这次是根据…

C++ //练习 10.19 用stable_partition重写前一题的程序,与stable_sort类似,在划分后的序列中维持原有元素的顺序。

C Primer&#xff08;第5版&#xff09; 练习 10.19 练习 10.19 用stable_partition重写前一题的程序&#xff0c;与stable_sort类似&#xff0c;在划分后的序列中维持原有元素的顺序。 环境&#xff1a;Linux Ubuntu&#xff08;云服务器&#xff09; 工具&#xff1a;vim …

【buuctf-gakki】

binwalk 查看图片&#xff0c;发现有 rar 文件&#xff0c;提取后如上图所示&#xff08;flag.txt为已经解压后出来的&#xff09;其中这个 rar 需要用 archpr爆破一下 打开后一个 flag.txt 一堆杂乱无章的字符&#xff0c;需要用到 python 脚本进行词频统计&#xff0c;我们…

专家教你学汽车美容护理,汽车美容师职业技能教学

一、教程描述 本套汽车美容教程&#xff0c;大小2.52G&#xff0c;61个文件。 二、教程目录 01-大家跟我学汽车美容&#xff08;共30课时&#xff09; 02-汽车内外饰物的安装&#xff08;共15课时&#xff09; 03-汽车必需设施的安装&#xff08;共13课时&#xff09; 04…

测开新手:pytest+requests+allure自动化测试接入Jenkins学习

最近在这整理知识&#xff0c;发现在pytest的知识文档缺少系统性&#xff0c;这里整理一下&#xff0c;方便后续回忆。 在python中&#xff0c;大家比较熟悉的两个框架是unittest和pytest&#xff1a; Unittest是Python标准库中自带的单元测试框架&#xff0c;Unittest有时候…

图论 - Trie树(字符串统计、最大异或对)

文章目录 前言Part 1&#xff1a;Trie字符串统计1.题目描述输入格式输出格式数据范围输入样例输出样例 2.算法 Part 2&#xff1a;最大异或对1.题目描述输入格式输出格式数据范围输入样例输出样例 2.算法 前言 本篇博客将介绍Trie树的常见应用&#xff0c;包括&#xff1a;Trie…

实验室记账项目(java+Mysql+jdbc)

前言&#xff1a; 因为自己学习能力有限和特殊情况必须要找一个项目来做&#xff0c;但是上网搜的那些项目有两种&#xff08;一种是技术太多&#xff0c;自己能力不够&#xff1b;一种是技术太少&#xff0c;项目太简单&#xff09;导致都不适合本人&#xff0c;本人现有技术只…

店务管理系统:都有哪些功能,是否是高效管理店面的神器

hello&#xff0c;我是贝格前端工场&#xff0c;直接给大家介绍了各类通用的B端管理系统&#xff0c;受到了大家的欢迎。本次开始介绍针对具体行业的管理系统该如何设计和开发&#xff0c;这次分享——店务管理系统&#xff0c;欢迎大家持续关注、点赞&#xff0c;如有系统定制…

使用python实现一个SCP小工具

源码地址&#xff1a; ssh_scp 工具截图&#xff1a; 一个简易的scp文件上传下载小工具&#xff0c;用来上传或下载一些小文件。 目前只适用于windows&#xff0c; 使用方法&#xff1a; 前提&#xff1a; 工具同级目录&#xff0c;创建一个ssh_commands.json文件。用来存储配…

网络攻防之CVE-2020-15778漏洞的复现及修复详细过程

目录 漏洞描述 实验环境 漏洞复现 漏洞修复 漏洞扩展 漏洞描述 (1)漏洞编号:CVE-2020-15778 (2)CVE官网对该漏洞的解释 (3)漏洞简介:2020年6月9日,研究人员Chinmay Pandya在Openssh中发现了一个漏洞,于7月18日公开。OpenSSH的8.3p1中的scp允许在scp.c远程功能中注入命…

Sqli-labs靶场第14关详解[Sqli-labs-less-14]

Sqli-labs-Less-14 #手工注入 post传参了 根据题目看&#xff0c;像一个登录页面&#xff0c;尝试使用布尔型盲注测试能否登录网站 1. Username输入a" 测试是否会有报错&#xff0c;burp抓包 报错&#xff1a;syntax to use near "a"" and password&q…

【Java文件报错】Cannot resolve symbol ‘println‘ 【及解决】

一、问题描述 在Java源代码文件中&#xff0c;使用 System.out.println() 语句进行输出&#xff0c;编译器提示“Cannot resolve symbol ‘println’&#xff08;无法解释关键字&#xff09;”, println飘红。报错代码及报错截图如下所示。 import java.io.*;public class St…

【Java】面向对象之多态超级详解!!

文章目录 前言一、多态1.1 多态的概念1.2 多态的实现条件1.3 重写1.3.1方法重写的规则1.3.2重写和重载的区别 1.4 向上转型和向下转型1.4.1向上转型1.4.2向下转型 1.5 多态的优缺点1.5.1 使用多态的好处1.5.2 使用多态的缺陷 结语 前言 为了深入了解JAVA的面向对象的特性&…

TypeScript 哲学 - 2、Narrowing

四种类型守卫 1、truthiness narrowing 2、 3、 4、 control flow analysis