C语言学习系列-->【关于qsort函数的详解以及它的模拟实现】

news2025/1/10 17:21:18

在这里插入图片描述

文章目录

  • 一、概述
  • 二、qsort函数参数介绍
  • 三、qsort实现排序
    • 3.1 qsort实现整型数组排序
    • 3.2 qsort实现结构体数组排序
  • 四、模拟实现qsort函数

一、概述

对数组的元素进行排序
对数组中由 指向的元素进行排序,每个元素字节长,使用该函数确定顺序。
此函数使用的排序算法通过调用指定的函数来比较元素对,并将指向它们的指针作为参数。

官方解释:

在这里插入图片描述

声明:

void qsort (void* base, size_t num, size_t size,int (*compar)(const void*,const void*));

qsort函数的参数

void* base
size_t num
size_t size
int( * compar )( const void * ,const void *)

二、qsort函数参数介绍

void qsort(void* base, //待排序数据的起始位置
         size_t num, //待排序数据的元素个数
          size_t size,//待排序数据的每个元素的大小
         int (*compar)(const void*p1, const void*p2));//函数指针 - 指针指向的函数是用来比较待排序数据中两个元素大小关系的

关于void * 的介绍:
void * 是一个无具体指向的指针类型
任何类型的指针变量都i可以存放在void中
void * 不能解引用

其中两个void*类型的参数 p1 和 p2 用来存放数组中待比较的两个元素的地址。如果compar函数的返回值小于0,会把p1指向的元素排到p2指向的元素前面;如果返回值等于0,不会改变p1和p2指向的元素位置;如果返回值大于0,会把p1指向的元素排到p2指向的元素后面。

三、qsort实现排序

3.1 qsort实现整型数组排序

# define _CRT_SECURE_NO_WARNINGS

#include<stdio.h>
#include<stdlib.h>

int comper(const void* e1, const void* e2)
{
    //通过强制类型转换,比较e1,e2.
	return *(int*)e1 - *(int*)e2;//void* 不能解引用
}

int main()
{
	int arr[] = { 5,3,6,7,8,1,9,4,2,0 };
	int sz = sizeof(arr) / sizeof(arr[0]);
    //传入参数
	qsort(arr, sz, sizeof(arr[0]), comper);
	//打印排序后的数组
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

在这里插入图片描述

3.2 qsort实现结构体数组排序

按照年龄大小的方式进行排序

# define _CRT_SECURE_NO_WARNINGS

#include<stdio.h>
#include<stdlib.h>

struct Stu
{
	char name[20];
	int age;
};

int comper_by_age(const void* e1, const void* e2)
{
	return ((struct Stu*)e1)->age - ((struct Stu*)e2)->age;  //结构体指针不需要解引用
}

int main()
{
	struct Stu s[] = { {"zhangsan",20},{"lisi",30},{"wangwu",25} };
	int sz = sizeof(s) / sizeof(s[0]);

	qsort(s, sz, sizeof(s[0]), comper_by_age);

	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%s %d\n", s[i].name, s[i].age);
	}
	return 0;
}

运行结果:

zhangsan 20
wangwu 25
lisi 30

按照名字进行排序

# define _CRT_SECURE_NO_WARNINGS

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

struct Stu
{
	char name[20];
	int age;
};

int comper_by_name(const void* e1, const void* e2)
{
	return strcmp(((struct Stu*)e1)->name, ((struct Stu*)e1)->name);//名字是字符串,通过strcmp函数来比较
}

int main()
{
	struct Stu s[] = { {"zhangsan",20},{"lisi",30},{"wangwu",25} };
	int sz = sizeof(s) / sizeof(s[0]);

	qsort(s, sz, sizeof(s[0]), comper_by_name);

	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%s %d\n", s[i].name, s[i].age);
	}
	return 0;
}

运行结果:

lisi 30
wangwu 25
zhangsan 20

在这里插入图片描述

四、模拟实现qsort函数

程序员A:写一个bubble_sort()函数,可以让别人直接拿来调用

于是程序员A想要利用冒泡排序的方式,来模拟实现qsort()函数排序

qsort的底层是通过快速排序来实现的

为了能对任意数组进行排序,程序员A对冒泡排序进行了一定的更改

和qsort函数一样,bubble_sort也需要传入四个参数:

void* arr   //接收首元素地址
size_t sz   //接收元素个数
size_t width  //接收元素宽度
int(*comper)(const void*e1,const void*e2)

于是,

void bubble_sort(void*arr,size_t sz,size_t width,int(*comper)(const void*e1,const void*e2))

现在需要完成bubble_sort内部,也就是实现排序

void bubble_sort(void* arr, size_t sz, size_t width, int(*comper)(const void* e1, const void* e2))
{
	size_t i = 0;
	//趟数
	for (i = 0; i < sz - 1; i++)
	{
		//一趟冒泡排序的过程
		size_t 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;
			}

但是,这只适用于整型,不通用

那么,如何去比较呢?如何去交换两个元素呢?

for (j = 0; j < sz-1-i; j++)
		{
			if (comper((char*)arr+j*width,(char*)arr+(j+1)*width)>0)
			//把arr强转为char*,arr就可以正常使用
			//char类型指针+1只会跳过一个字节
			//+j*width表示跳过j个元素
			{
				//交换
				//由于这里的数组名已经被转为char类型的指针
				//所以要交换数组中的元素,就只能一个字节一个字节进行交换
				Swap((char*)arr + j * width, (char*)arr + (j + 1) * width,width);
				//前两个参数是待交换元素的地址,第三个参数是元素的宽度
			}
		}

这样,就把交换条件普适化了,不只是能用在整型类型中

那么…交换呢?

根据以前的经验,我们知道使得两个元素交换,可以引入一个新的变量来暂时存一下,从而去交换,但是这有限制。

解决方案:一个字节一个字节地交换

我们将交换地函数,封装在这里面:

Swap((char*)arr + j * width, (char*)arr + (j + 1) * width,width)

对Swap函数进行加工:

void Swap(char* ele1, char* ele2,int width)
{
	int i = 0;
	for (i = 0; i < width; i++)
	{
		char tmp = *ele1;
		*ele1 = *ele2;
		*ele2 = tmp;
		ele1++;
		ele2++;
	}
}

这样,程序员A就将 bubble_sort()函数完成了

程序员B要想是使用该函数,直接引入 bubble_sort函数,自己写一个比较函数就可以了。

在这里插入图片描述

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

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

相关文章

Vue中ElementUI结合transform使用时,发现弹框定位不准确问题

在近期开发中&#xff0c;需要将1920*1080放到更大像素大屏上演示&#xff0c;所以需要使用到transform来对页面进行缩放&#xff0c;但是此时发现弹框定位出错问题&#xff0c;无法准备定位到实际位置。 查看element-ui官方文档无果后&#xff0c;打算更换新的框架进行开发&am…

学校宿舍门禁:如何做好考勤管理?

随着科技的不断发展&#xff0c;传统的考勤方式逐渐显现出其局限性&#xff0c;而人脸识别技术作为一种快速、准确、无需直接接触的身份验证手段&#xff0c;为宿舍管理带来了全新的可能性。 宿舍管理能够让管理员随时通过系统监控宿舍内的人员流动情况&#xff0c;当系统检测到…

【Nginx】Nginx 简介

Ngnix 特点 模块化设计&#xff1a;良好的扩展性&#xff0c;可以通过模块方式进行功能扩展。高可靠性&#xff1a;主控进程和 worker 是同步实现的&#xff0c;一个 worker 出现问题&#xff0c;会立刻启动另一个 worker。内存消耗低&#xff1a;一万个长连接&#xff08;kee…

ASE 基础知识

笔记&#xff1a; 1&#xff0c;颜色&#xff0c;贴图 2&#xff0c;加减乘除 3&#xff0c;菲涅尔、sin&#xff0c;float、vector、time 4&#xff0c;漫反射&#xff0c;法线&#xff0c;自发光&#xff0c;金属度&#xff0c;反射&#xff0c;AO明暗&#xff0c;折射&#…

[保研/考研机试] KY190 查找第K小数 北京邮电大学复试上机题 C++实现

题目链接&#xff1a; 查找第K小数_牛客题霸_牛客网查找一个数组的第K小的数&#xff0c;注意同样大小算一样大。 如 2 1 3 4 5 2 第三小数。题目来自【牛客题霸】https://www.nowcoder.com/share/jump/437195121692786918857 描述 查找一个数组的第K小的数&#xff0c;注意…

正中优配:创业板一天最多涨多少?

创业板是我国股票商场的一个特定板块&#xff0c;它首要涵盖了草创公司、小微企业和新型产业的股票买卖。作为股票商场的重要组成部分&#xff0c;创业板的涨跌对于投资者和商场参与者来说具有必定的影响力。那么&#xff0c;创业板一天最多能够涨多少呢&#xff1f;本文将从多…

2023年机遇与挑战:裁员速度逐渐趋缓 | 百能云芯

随着2023年已经过半&#xff0c;美国湾区的科技公司仍在进行着内部结构的调整&#xff0c;以适应不断变化的市场环境。然而&#xff0c;从裁员人数来看&#xff0c;这一调整似乎已经进入了一个步伐逐渐放缓的阶段。 根据公开文件显示&#xff0c;英特尔、SPT MicroElectronics和…

配置禁止生成可执行文件-火绒法

防止黑客利用漏洞上传可执行文件的方法&#xff0c;可以尝试通过文件服务器资源管理器(FSRM)设置文件屏蔽防止黑客利用漏洞上传特定类型的非法文件(.asp .aspx .jsp .php)。要是系统问题不能使用(FSRM)&#xff0c;可以用火绒来干这个事儿。方法如下&#xff1a; 配置方法 火…

Python“牵手”阿里巴巴商品详情API接口运用场景及功能介绍

阿里巴巴电商API接口是针对阿里巴巴提供的电商服务平台&#xff0c;为开发人员提供了简单、可靠的技术来与阿里巴巴电商平台进行数据交互&#xff0c;实现一系列开发、管理和营销等操作。其中包括商品详情API接口&#xff0c;通过这个API接口商家可以获取商品的详细信息&#x…

大神闭关7天整理!137页Python学习笔记,全面总结看这一篇就够了

Python作为当下最热门的编程语言之一&#xff0c;从前几年一直火到现在&#xff0c;并且还有更甚的趋势。不仅吸引了众多业内人士&#xff0c;圈外人士也纷纷加入了学习Python的阵营之中。 但很多朋友在学习Python时&#xff0c;直呼&#xff1a;太难了&#xff0c;学不会&…

解锁ChatGLM-6B的潜力:优化大语言模型训练,突破任务困难与答案解析难题

解锁ChatGLM-6B的潜力&#xff1a;优化大语言模型训练&#xff0c;突破任务困难与答案解析难题 LLM&#xff08;Large Language Model&#xff09;通常拥有大量的先验知识&#xff0c;使得其在许多自然语言处理任务上都有着不错的性能。 但&#xff0c;想要直接利用 LLM 完成…

wazuh安装与使用

目录 一、wazuh安装 二、wazuh使用 一、wazuh安装 下载&#xff1a;https://wazuh.com 可以直接安装OVA这个&#xff0c;然后导入到Linux中就可以使用了。 导入完毕后开启&#xff0c;使用远程连接工具进行连接&#xff0c;出现以下画面则成功了。 之后可以看一下图形化界面…

9 - 蓝图

蓝图: 将项目分成一个个单独的app模块&#xff0c;然后将所有app分配不同的处理功能&#xff0c;通过路由分配将它们连接成一个大项目 目录结构: 搭建框架: (1). 新键apps 包,编辑__init__.py文件 from flask import Flask import settings from apps.user.view import user_b…

AS中回退git历史版本并删除历史提交记录

当您想把某个版本后的代码删除&#xff0c;回滚到指定的版本。可以使用一下的方法。 一、打开AS中git历史提交窗口 二、选择需要回滚的版本选项&#xff0c;右键弹出菜单。选择Reset Current Branch to Here... 三、选择 Hard 选项 soft&#xff1a;将合并的更改应用到当前分支…

【微服务】Ribbon的实现原理

1、场景&#xff1a;这里有两个服务&#xff0c;user-server和store-server 1.1、user服务 接口&#xff1a; package com.lkx.user.controller;import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController…

【vue+uniapp】切换本页面(点击导航按钮)就刷新接口

查阅资料&#xff1a;uni-app官网 点击导航中图标&#xff0c;就执行的方法&#xff08;和methods同级&#xff09;&#xff1a; onTabItemTap(e) {this.getTaskTotal(); },

ubuntu执行jmeter端口不够用报错(Address not available)

ubuntu执行jmeter端口不够用报错(Address not available) 解决方案 // 增加本地端口范围 echo 1024 65000 > /proc/sys/net/ipv4/ip_local_port_range// 启用快速回收TIME_WAIT套接字 sudo sysctl -w net.ipv4.tcp_tw_recycle 1// 启用套接字的重用 sudo sysctl -w net.ipv4…

LLMs 缩放法则和计算最优模型Scaling laws and compute-optimal models

在上一个视频中&#xff0c;您探讨了训练大型语言模型的计算挑战。在这里&#xff0c;您将了解关于模型大小、训练、配置和性能之间关系的研究&#xff0c;以确定模型需要多大。请记住&#xff0c;预训练期间的目标是最大化模型的学习目标性能&#xff0c;即在预测令牌时最小化…

【LeetCode-中等题】53. 最大子数组和

题目 题解一&#xff1a;暴力解法&#xff1a; //暴力解法 每个元素为都循环一次&#xff0c;持续更新最大值int maxS Integer.MIN_VALUE;for(int i 0;i<nums.length;i){int num 0;for(int j i;j<nums.length;j){num numnums[j];maxS Math.max(maxS,num);}}retur…

数据库——事务,事务隔离级别

文章目录 什么是事务?事务的特性(ACID)并发事务带来的问题事务隔离级别实际情况演示脏读(读未提交)避免脏读(读已提交)不可重复读可重复读防止幻读(可串行化) 什么是事务? 事务是逻辑上的一组操作&#xff0c;要么都执行&#xff0c;要么都不执行。 事务最经典也经常被拿出…