『C语言进阶』qsort函数及模拟实现

news2024/11/26 4:40:28

在这里插入图片描述
🔥博客主页 小羊失眠啦
🔖系列专栏 C语言
🌥️每日语录没有退路,只能让自己变得强大
❤️感谢大家点赞👍收藏⭐评论✍️


在这里插入图片描述

前言

在上篇指针进阶中,我们对函数指针、函数指针数组、函数指针数组指针以及回调函数有了一定的了解,文章末尾简单的对qsort函数进行了展示,今天我们主要以qsort函数用冒泡排序的模拟实现以及各种类型的排序,后面针对指针和数组一些细节上的讲解~

一、qsort函数介绍

qsort是一个库函数,快速排序的方法来实现的, 头文件是<stdlib.h>
qsort库函数:
void qsort( void *base, size_t num, size_t size, int (*compare )(const void *, const void *) );
传入的参数,一个是指针,一个整形,一个整形,一个函数指针;
base 数组首元素(就是数组名),num数组里有多少个元素,size每个元素的大小(单位是字节),compare指向数组中比较方式的函数指针;

功能介绍

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


二、qsort函数的应用

由于使用qsort函数时,并不知道要排序的元素是什么类型,这时需要写一个compare函数,并对立面的参数强制类型转化

2.1 整型数组排序

#include<stdio.h>
#include<stdlib.h>
void Print(int arr[], int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
}

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

int main()
{
	int arr[] = { 1,3,7,5,8,9,0,2,4,6 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	qsort(arr, sz, sizeof(arr[0]), com_int);
	Print(arr, sz);
	return 0;
}

运行结果:

0 1 2 3 4 5 6 7 8 9

2.2 浮点型数组排序

#include <stdio.h>
#include <stdlib.h>
void Print(double arr[], int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%2.2lf ", arr[i]);
	}
}
int com_double(const void* e1, const void* e2)
{
	return *(double*)e1 - *(double*)e2;
}
int main()
{
	double arr[6] = { 8.26, 65.5,	73.53,	43.45,	95.3,	19.5 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	qsort(arr, sz, sizeof(arr[0]), com_double);
	Print(arr, sz);
	return 0;
}

运行结果:

8.26 19.50 43.45 65.50 73.53 95.30

2.3 字符型排序

#include <stdio.h>
#include <stdlib.h>
void Print(char arr[],int sz)
{
	for (int i = 0; i < sz; i++)
		printf("%c ", arr[i]);
}
int char_sort(const void* e1, const void* e2)
{
	return (*(char*)e1) - (*(char*)e2);
}
int main()
{
	char arr[10] = { 'd','g','b','a','e','i','h','c','j','f' };
	int sz = sizeof(arr) / sizeof(arr[0]);
	qsort(arr, sz, sizeof(arr[0]), char_sort);
	Print(arr, sz);
	return 0;
}

运行结果:

a b c d e f g h i j

2.4 结构体数组排序

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

typedef struct student
{
	char name[15];
	int age;
	float score;
}S;

void Print(struct student* stu,int sz)
{
	for (int i = 0; i < sz; i++)
	{
		printf("%-12s %-5d %-5.2fm\n", stu[i].name, stu[i].age, stu[i].score);
	}
}

int com_age(const void* e1, const void* e2)
{

	return (((S*)e1)->age - ((S*)e2)->age);
}

int com_score(const void* e1, const void* e2)
{

	return ((S*)e1)->score - ((S*)e2)->score;
}

int com_name(const void* e1, const void* e2)
{
	return strcmp(((S*)e1)->name, ((S*)e2)->name);
}

int main()
{
	
	S stu[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 sz = sizeof(stu) / sizeof(stu[0]), input = 0;
	qsort(stu, sz, sizeof(stu[0]), com_age);
	printf("姓名	    年龄   身高\n");
	Print(stu, sz);
	return 0;
}

运行结果:

姓名        年龄   身高
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模拟实现(冒泡排序)

3.1 冒泡排序

#include <stdio.h>
void Print(int arr[], int sz)
{
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
}
void bubble_sort(int arr[],int sz)
{
	int i = 0;
	for (i = 0; i < sz - 1; i++)
	{
		int j = 0;
		for (j = 0; j < sz - i - 1; j++)
		{
			if (arr[j] > arr[j + 1])
			{
				int tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
			}
		}
	}
}
int main()
{
	int arr[] = { 5,3,7,6,1,8,9,2,4,0 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	bubble_sort(arr,sz);
	Print(arr, sz);
	return 0;
}

3.2 qsort模拟实现

第一步:冒泡函数的参数
首先要修改的是冒泡排序函数的参数
void bubble_sort(void* arr,size_t num,size_t width,int(*compare)(const void*,const void*))
需要注意的是qsort函数事先是不知道传过来的数组是什么类型,所以都先用void*接受

第二步:比较元素的方法
在对两元素比较时,事先是不知道类型的

  1. 要先将arr强制类型转化为char*,因为一个字节是类型的最小单位,这时候就需要用到width了
  2. 元素的比较方式不再是单一的相减,这里用到自定义函数,元素的比较方式函数

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

第三步:交换函数
修改为char*类型进行交换

swap(char* e1, char* e2, int width)
{
	int i = 0;
	char p = 0;
	for (i = 0; i < sz; i++)
	{
		p = *(e1 + i);
		*(e1 + i) = *(e2 + i);
		*(e2 + i) = p;
	}
}

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

代码展示:

#include <stdio.h>
void Print(int arr[], int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
}

void swap(char* e1, char* e2, int width)
{
	int i = 0;
	char p = 0;
	for (i = 0; i < width; i++)
	{
		p = *(e1 + i);
		*(e1 + i) = *(e2 + i);
		*(e2 + i) = p;
	}
}

void bubble_sort(void* base, int sz, int width, int (*cmp)(const void* e1, const void* e2))
{
	int i = 0;
	int j = 0;
	for (i = 0; i < sz; i++)
	{
		for (j = 0; j < sz - 1 - i; j++)
		{
			if (cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0)
			{
				swap((char*)base + j * width, (char*)base + (j + 1) * width, width);//一个字节一个字节的交换
			}
		}
	}
}

int com_int(const void* e1, const void* e2)
{
	return *(int*)e1 - *(int*)e2;
}
int main()
{
	int arr[] = { 1, 3, 6, 2, 0, 9, 4, 8, 5, 7 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	bubble_sort(arr, sz, sizeof(arr[0]), com_int);
	Print(arr, sz);
	return 0;
}

qsort函数用冒泡排序的模拟实现就讲到这里,指针的进阶也到此结束了,接下来对指针和数组一些细节上的补充到时候会在文章见分晓,欢迎大家互三,一起交流,互相学习~~

在这里插入图片描述

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

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

相关文章

深入理解 Swift 新并发模型中 Actor 的重入(Reentrancy)问题

问题现象 我们知道,Swift 5.5 引入的新并发模型极大简化了并行逻辑代码的开发,更重要的是:使用新并发模型中的 Actor 原语可以大大降低并发数据竞争的可能性。 不过,即便 Actor 有如此神奇之功效,它也不是“万能药”,仍不能防止误用带来的问题。比如:Actor 重入(Reen…

132.【MySQL_进阶篇】

MySQL_进阶 (一)、存储引擎1.MySQL体系结构(1).连接层(2).服务层(3).引擎层(4).存储层 2.存储引擎简介(1).查看某张表的数据引擎(2).展示此版本支持的所有存储引擎(3).创建表my_myisam,并指定MyIASM存储引擎(4).存储引擎示列 3.存储引擎 _ Innodb(1).Innodb 介绍(2).Innodb 特点…

通过 HelpLook ChatBot AI自动问答机器人降低客户服务成本

在当今竞争激烈的商业环境中&#xff0c;提供卓越的客户服务对于维持忠诚的客户群和推动业务增长至关重要。客户服务涵盖了公司与其客户之间的所有互动&#xff0c;包括解答问题、解决问题和提供支持。它在塑造客户对品牌的看法方面起着关键作用&#xff0c;并且可以显著影响他…

NSSSCTF做题(2)

1.[BJDCTF 2020]easy_md5 打开页面发现没什么东西&#xff0c;只有一个提交表单&#xff0c;然后url会显示你提交的信息 源代码里也看不到什么 &#xff0c;用dirsearch扫一下&#xff0c;这些是扫出来的数据 抓包看到了提示 hint: select * from admin where passwordmd5($pas…

【文件操作——详细讲解】

1. 为什么使用文件&#xff1f;&#x1f9d0; 如果没有⽂件&#xff0c;我们写的程序的数据是存储在电脑的内存中&#xff0c;如果程序退出&#xff0c;内存回收&#xff0c;数据就丢失了&#xff0c;等再次运⾏程序&#xff0c;是看不到上次程序的数据的&#xff0c;如果要将数…

cmd下scala退出命令

cmd下scala退出命令 &#xff1a;quit

checksec使用

checksec Relro&#xff1a;Full Relro&#xff08;重定位表只读&#xff09; Relocation Read Only&#xff0c; 重定位表只读。重定位表即.got 和 .plt个表。 Stack&#xff1a;No Canary found&#xff08;能栈溢出&#xff09; 栈保护。栈溢出保护是一种缓冲区溢出攻击缓解…

Docker 部署前端项目(非自动化)

部署前端项目 1. nginx配置文件1.1 nginxConf 2. 创建容器2.1 添加项目2.2 下载项目依赖2.3 打包前端项目2.4 创建容器2.5 查看容器 3. 视频演示4. 注意 1. nginx配置文件 1.1 nginxConf 首先你需要有nginx配置文件&#xff0c;你可以执行以下命令获取配置文件 # 安装镜像-生成…

JS进阶-闭包

概念&#xff1a;一个函数对周围状态的引用捆绑在一起&#xff0c;内层函数中访问到其外层函数的作用域 简单理解&#xff1a;闭包&#xff08;Closure&#xff09;内层函数外层函数的变量 function outer() {const a 1function f() {console.log(a)}f()} outer() 闭包作用…

最新商道融绿ESG数据(2015-2023)

数据简介&#xff1a;环境、社会和公司治理&#xff08;environmental, social, and corporate governance, 简称ESG&#xff09;方面的非财务信息已经普遍被用于评估企业在可持续发展方面的绩效。投资者通过考察上市公司的ESG绩效&#xff0c;便于识别企业面临的风险&#xff…

L1-033 出生年 c++解法

一、题目再现 以上是新浪微博中一奇葩贴&#xff1a;“我出生于1988年&#xff0c;直到25岁才遇到4个数字都不相同的年份。”也就是说&#xff0c;直到2013年才达到“4个数字都不相同”的要求。本题请你根据要求&#xff0c;自动填充“我出生于y年&#xff0c;直到x岁才遇到n个…

ElementUI之动态树+数据表格+分页

目录 一.ElementUI动态树 编写left.vue界面 配置url ​编辑 建立书籍的页面 编写路由 显示子主键的类 测试结果 二.ElementUI数据表格分页 在booklist中编写数据表格和分页 编写url路径 测试结果 ​编辑 一.ElementUI动态树 编写left.vue界面 <template>…

OpenAI 更新 ChatGPT:支持图片和语音输入【附点评】

一、消息正文 9月25日消息,近日OpenAI宣布其对话AI系统ChatGPT进行升级,添加了语音输入和图像处理两个新功能。据OpenAI透露,这些新功能将在未来两周内面向ChatGPT Plus付费用户推出,免费用户也将很快可以使用这些新功能。这标志着ChatGPT继续朝着多模态交互的方向发展,为用户提…

3D 视觉市场空间广阔,3D 感知龙头全技术路线布局

3D 视觉市场尚处在发展早期,空间广阔 人类 70%以上信息通过眼睛获取,对于机器而言,视觉感知也是其“智能化”升级的重要基础。3D 成像让每一个像素除 x、y 轴数据外,还有 z 轴(深度/距离)数据。围绕着人体、物体、空间扫描一圈,就能得到点云图和精准的“1:1”还原的 3D …

abaqus命令行基础

1.abaqus命令行基础 使用 abaqus 时&#xff0c;如果需要进行参数分析&#xff0c;就需要生成大量的模型&#xff0c;这时一般会使用python文件定义函数进行批量生成并计算。 如果已经生成了计算文件(*.inp文件)&#xff0c;那么就可以直接在命令行进行求解&#xff0c;abaqu…

自动化测试框架pytest命令参数

【软件测试面试突击班】如何逼自己一周刷完软件测试八股文教程&#xff0c;刷完面试就稳了&#xff0c;你也可以当高薪软件测试工程师&#xff08;自动化测试&#xff09; 失败后停止 使用下面的参数可以让测试在第1(N)次测试失败后停止&#xff1a; pytest ‐x # 第一次测试…

【大数据存储与处理】1. hadoop单机伪分布安装和集群安装

0. 写在前面 0.1 软件版本 hadoop2.10.2 ubuntu20.04 openjdk-8-jdk 0.2 hadoop介绍 Hadoop是一个由Apache基金会所开发的分布式系统基础架构。用户可以在不了解分布式底层细节的情况下&#xff0c;开发分布式程序。充分利用集群的威力进行高速运算和存储。Hadoop实现了一个…

数据结构_红黑树

1、二叉树 每一个分支不能超过两个 2、 排序数/查找树 在二叉树的基础上&#xff0c;元素是有大小顺序的左 子树 小&#xff0c;右 子树 大 3、平衡树 左孩子数 和 右孩子数 相等 4、不平衡树 5、 红黑树 特点&#xff1a;趋近于平衡树&#xff0c;查询的速度非常的快&#xf…

【论文笔记】A Review of Motion Planning for Highway Autonomous Driving

文章目录 I. INTRODUCTIONII. CONSIDERATIONS FOR HIGHWAY MOTION PLANNINGA. TerminologyB. Motion Planning SchemeC. Specificities of Highway DrivingD. Constraints on Highway DrivingE. What Is at Stake in this Paper III. STATE OF THE ARTA. Taxonomy DescriptionB…

全新iphone15 pro max拆解,内部元件供应链曝光 | 百能云芯

苹果顶级版iPhone 15 Pro Max热销&#xff0c;国外维修网站ifixit拆解内部零组件后评估&#xff0c;苹果在电源、无线通讯、音频等关键元件比重增加。台企华邦电子供应编码型快闪存储器&#xff08;NOR Flash&#xff09;。 苹果&#xff08;Apple&#xff09;iPhone 15 Pro Ma…