【C语言】冒泡排序的快排模拟

说到排序,必然绕不开两个排序,冒泡排序快速排序
冒泡排序是大多数人的启蒙排序,因为他的算法简单。但效率不高,便于新手理解;
而快速排序是集大成之作,效率最高,使用最为广泛。

今天这篇文章带来如何使用qsort(quick sort,快速排序),和如何使用冒泡排序的快速排序的模拟。
也会在不久后讲解几大排序的算法。

目录

  • 冒泡排序:
  • qsort的参数设计:
  • 冒泡排序的快排模拟:

冒泡排序:

开始之前先来回顾一下冒泡排序的实现

冒泡排序的思想是让数组的元素从头开始两两比较,大的放在后边(根据情况定),解决完一个元素在进行下一个,如下图。

在这里插入图片描述
从上图中我们发现排序第一趟要进行5次(len-1次)
而一趟可以解决1个元素的位置(当剩最后一个元素时不用排序)
所以可以得到一共需要进行5趟(len-1趟)
故可以写一个外层for循环模拟趟数,循环变量为i,从0开始
在这里插入图片描述
第二次时就进行4
每趟都会减少一个需要排序的元素,与外层循环变量i有关
故我们控制一趟次数的内循环可以根据i来写出适当的表达式

代码实现:

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

这样一个朴实无华的冒泡排序就完成了。
接下来研究qsort

一一一一一一一一一分割线一一一一一一一一

qsort的参数设计:

登录网站cpulsplus.com,可以查询qsort函数信息

cpp网站链接
在这里插入图片描述
觉得难以理解不要紧,下边有详细的解释。

我们发现qsort有4个参数

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

1.void*base
大家看到这个肯定就懵了,啥是void*
void*也是一种指针类型,不过他可以接收任意类型的数据;
什么?任意类型,这也就说明qsort不只可以排序整形,字符,甚至结构体都可以排序
base就是数组的数组名,因为知道数组在哪里才可以进行排序。

2.size_t num
size_tsizeof这个操作符的返回值类型,本质是unsigned类型。
num是指数组中元素个数的多少

3.size_t size
排序有了数组名,有了个数就可以排序了吗?
想到冒泡排序好像就是这样,但是,别忘记qsort可以排序任意类型,这也就意味着我们不仅需要知道数组名与元素个数,还需要知道排序的是什么类型,也就是多少字节,size就是数组中每个元素的字节大小。

4.int (*compar)(const void*,const void*))
仔细看,发现他像什么?
没错是个函数指针,他的类型是int (*)(const void*,const void*)),为什么qsort需要传参一个函数指针,因为qsort需要知道两个数据间是如何比较,这取决于使用者的想法,比如结构体你想按照其中的字符串比较还是整形比较

这是比较函数的返回值:
在这里插入图片描述
当返回值小于0 ,p1指向元素被排在p2指向元素左边。即[*p1, *p2];

当返回值大于0 ,p1指向元素被排在p2指向元素右边。即[*p2, *p1];

当返回值等于0 ,p1指向元素和p2指向元素顺序不确定。

即e1指向的值大于e2指向的值,返回正数,否则返回负数,相等时返回0(默认升序)
知道了参数是什么,那我们应该怎样使用呢?
不要看着感觉复杂,其实很简单

#include <stdio.h>
//qosrt函数的使用者得实现一个比较函数
int int_cmp(const void * p1, const void * p2)
{return (*( int *)p1 - *(int *) p2);//因为我们比较的是int类型,所以需要将e1,e2强转后再解引用//void*类型是不可以解引用的
}
//注意比较函数的返回值
e1>e2返回一个正数
int main()
{int arr[] = { 1, 3, 5, 7, 9, 2, 4, 6, 8, 0 };int i = 0;qsort(arr, //数组名sizeof(arr) / sizeof(arr[0]), //数组的元素个数sizeof (int),//每个元素类型int_cmp);//比较函数for (i = 0; i< sizeof(arr) / sizeof(arr[0]); i++){printf( "%d ", arr[i]);}printf("\n");return 0;
}

这就实现了如何使用qsort。

一一一一一一一一一分割线一一一一一一一一

冒泡排序的快排模拟:

那么如果我们将qsort中的参数放到冒泡排序中,该如何以qsort的方式实现冒泡排序呢?
我们发现,整体的逻辑不需要改动,需要改动的是两个元素的比较需要使用我们自己定义的cmp函数
那么请看代码,会在代码中解释大家的各种疑问
代码实现:

先来看函数的主体部分:,只是改写了参数

int main()
{int arr[] = { 9, 8, 7, 6, 5, 4, 3, 2, 1 ,0};int len = sizeof(arr) / sizeof(arr[0]);//参数改成qsort形式的参数bubble_sort(arr, len, sizeof(arr[0]), cmp);for (int i = 0; i < len; i++) {printf("%d ", arr[i]);}return 0;
}

然后看冒泡排序的实现:

//比较函数
int cmp(const void* e1, const void* e2)
{return (*(int*)e1 - *(int*)e2);
}void bubble_sort(void*base,int len,int width,int(*cmp)())
{for (int i = 0; i < len - 1; i++){for (int j = 0; j < len - 1 - i; j++){if (cmp((char*)base+width*j, (char*)base + width * (j+1))> 0)
//因为base是void*类型,需要强转成(char*),因为char*是最小的单位,
//容易操作,同时利用width和j得出当前元素与下一个元素的地址,
//在cmp中强转为int*进行比较
//当返回值为正数1说明e1指向的数大于e2指向的,需要交换{swap((char*)base + width * j, width);//交换函数}}}
}

交换函数:
共循环width次,因为width为字节大小,而我们是char*类型,只有1字节,我们通过for循环来交换

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

在这里插入图片描述
一一一一一一一一一分割线一一一一一一一一
整体代码:

int cmp(const void* e1, const void* e2)
{return (*(int*)e1 - *(int*)e2);
}
void swap(char* p,int width)
{for (int i = 0; i < width; i++){char tmp = *(p+i);*(p+i) = *(p + i + width);*(p + i + width) = tmp;}
}
void bubble_sort(void*base,int len,int width,int(*cmp)())
{for (int i = 0; i < len - 1; i++){for (int j = 0; j < len - 1 - i; j++){if (cmp((char*)base+width*j, (char*)base + width * (j+1)) > 0){swap((char*)base + width * j, width);}}}
}int main()
{int arr[] = { 9, 8, 7, 6, 5, 4, 3, 2, 1 ,0};int len = sizeof(arr) / sizeof(arr[0]);bubble_sort(arr, len, sizeof(arr[0]), cmp);for (int i = 0; i < len; i++) {printf("%d ", arr[i]);}return 0;
}

欢迎纠错与交流!

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

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

相关文章

单片机-芯片怎么看图连接

单片机连接数码管 硬件连接线路图 单片机中的IO口连接端子 J25 &#xff0c;J25 连接 2个电阻 PR14 &#xff0c;引出管脚 P22 &#xff0c;P23&#xff0c;P24 P22 、P23、P24 连接 3-8 译码器 三输入、8输出 8 输出 &#xff0c;连接8个LED1~LED8 用到三个芯片&#xff…

MATLAB 2023安装方法之删除旧版本MATLAB,安装新版本MATLAB

说明&#xff1a;之前一直使用的是MATLAB R2020b&#xff0c;但最近复现Github上的程序时&#xff0c;运行不了&#xff0c;联系作者说他的程序只能在MATLAB 2021之后的版本运行&#xff0c;因此决定安装最新版本的MATLAB。 系统&#xff1a;Windows 11 需要卸载的旧MATLAB 版…

redis面试题二

redis如何处理已过期的元素 常见的过期策略 定时删除&#xff1a;给每个键值设置一个定时删除的事件&#xff0c;比如有一个key值今天5点过期&#xff0c;那么设置一个事件5点钟去执行&#xff0c;把它数据给删除掉&#xff08;优点&#xff1a;可以及时利用内存及时清除无效数…

Mac版JFormDesigner IDEA插件安装(非商业用途)

前言 仅供个人开发者使用&#xff0c;勿用作商业用途。 仅供个人开发者使用&#xff0c;勿用作商业用途。 仅供个人开发者使用&#xff0c;勿用作商业用途。 感觉做了这些年开发&#xff0c;怎么感觉市场越搞越回去了。桌面应用又成主流了&#xff1f; 甲方让做桌面客户端&am…

Java String类(2)

String方法 字符串拆分 可以将一个完整的字符串按照指定的分隔符划分为若干个子字符串 相关方法如下&#xff1a; 方法功能String[ ] split(String regex)//以regex分割将字符串根据regex全部拆分String[ ] split(String regex, int limit)将字符串以指定的格式&#xff0c;拆…

Liquid UI和Fiori的区别

主要围绕以下几个方面就Liquid UI和Firor来进行比较&#xff1a; 开发周期开发成本稳定性和支援性平台架构 影响Firor决策的因素&#xff1a; 复杂的编程过程&#xff0c;Fiori对开发人员要求高&#xff0c;开发难度大&#xff0c;而Liquid UI让开发人员不需要懂SAP后端&…

jdk-8u371-linux-x64.tar.gz jdk-8u371-windows-x64.exe 【jdk-8u371】 全平台下载

jdk-8u371 全平台下载 jdk-8u371-windows-x64.exejdk-8u371-linux-x64.rpmjdk-8u371-linux-x64.tar.gzjdk-8u371-macosx-x64.dmgjdk-8u371-linux-aarch64.tar.gz 下载地址 迅雷云盘 链接&#xff1a;https://pan.xunlei.com/s/VNdLL3FtCnh45nIBHulh_MDjA1?pwdw4s6 百度…

无涯教程-JavaScript - TDIST函数

The TDIST function replaces the T.DIST.2T & T.DIST.RT functions in Excel 2010. 描述 该函数返回学生t分布的百分点(概率)​​,其中数值(x)是t的计算值,将为其计算百分点。 t分布用于小样本数据集的假设检验。使用此函数代替t分布的临界值表。 语法 TDIST(x,deg_fr…

Elasticsearch:利用矢量搜索进行音乐信息检索

作者&#xff1a;Alex Salgado 欢迎来到音乐信息检索的未来&#xff0c;机器学习、矢量数据库和音频数据分析融合在一起&#xff0c;带来令人兴奋的新可能性&#xff01; 如果你对音乐数据分析领域感兴趣&#xff0c;或者只是热衷于技术如何彻底改变音乐行业&#xff0c;那么本…

[管理与领导-67]:IT基层管理者 - 辅助技能 - 4- 职业发展规划 - 评估你与公司的八字是否相合

目录 前言&#xff1a; 一、概述 二、八字相合的步骤 2.1 企业文化是否相合 2.2.1 企业文化对职业选择的意义 2.2.2 个人与企业三观不合的结果 2.2.3 什么样的企业文化的公司不能加入 2.2 公司的发展前景 2.3 公司所处行业发展 2.4 创始人的三观 2.5 创始人与上司的…

docker安装grafana,prometheus,exporter以及springboot整合详细教程(GPE)

springboot项目ip:192.168.168.1 测试服务器ip:192.168.168.81 文章来自互联网,自己略微整理下,更容易上手,方便自己,方便大家 最终效果: node springboot 1.下载镜像 docker pull prom/node-exporter docker pull prom/mysqld-exporter docker pull google/cadvisor dock…

多维时序 | Matlab实现GRU-Adaboost和GRU多变量时间序列预测对比

多维时序 | Matlab实现GRU-Adaboost和GRU多变量时间序列预测对比 目录 多维时序 | Matlab实现GRU-Adaboost和GRU多变量时间序列预测对比预测效果基本介绍模型描述程序设计参考资料 预测效果 基本介绍 多维时序 | Matlab实现GRU-Adaboost和GRU多变量时间序列预测对比 模型描述 M…

TypeScript学习 + 贪吃蛇项目

TypeSCript简介 TypeScript是JavaScript的超集。它对JS进行了扩展&#xff0c;向JS中引入了类型的概念&#xff0c;并添加了许多新的特性。TS代码需要通过编译器编译为JS&#xff0c;然后再交由JS解析器执行。TS完全兼容JS&#xff0c;换言之&#xff0c;任何的JS代码都可以直…

python 之import与from import 导入库的解析与差异

文章目录 1. **使用import导入整个模块**&#xff1a;2. **使用from import导入特定内容**&#xff1a;注意事项别名的使用 在Python中&#xff0c;import和from import是用于导入模块中内容的两种不同方式。下面详细介绍它们的用法和差异&#xff1a; 1. 使用import导入整个模…

uni-app里使用webscoket

实现思路和vue中是一样的。如果想看思路可以看这篇文章&#xff1a;websocket 直接上可以运行的代码&#xff1a; 一、后端nodeJS代码&#xff1a; 1、新建项目文件夹 2、初始化项目&#xff1a; npm init -y 3、项目里安装ws npm i ws --save 4、nodeJS代码&#xff1…

第 112 场 LeetCode 双周赛题解

A 判断通过操作能否让字符串相等 I s 1 s1 s1和 s 2 s2 s2第 1 1 1、 2 2 2位若同位置不等&#xff0c;则 s 1 s1 s1交换对应的 i i i和 j j j位置&#xff0c;之后判断 s 1 s1 s1和 s 2 s2 s2是否相当 class Solution { public:bool canBeEqual(string s1, string s2) {for (i…

如何让看书变听书?

听书神器 安卓 页面简单&#xff0c;易操作&#xff0c;全网小说随便听 各种声音帮你读你喜欢听的小说&#xff0c;带你进入主人公世界 支持网页版小说、本地小说、图片&#xff0c;都能读给你听 想看小说&#xff0c;又怕伤眼睛的宝子&#xff0c;可以试试看&#xff01;…

手撕二叉平衡树

今天给大家带来的是平衡树的代码实现&#xff0c;如下&#xff1a; #pragma once #include <iostream> #include <map> #include <set> #include <assert.h> #include <math.h> using namespace std; namespace cc {template<class K, clas…

vue Cesium接入在线地图

Cesium接入在线地图只需在创建时将imageryProvider属性换为在线地图的地址即可。 目录 天地图 OSM地图 ArcGIS 地图 谷歌影像地图 天地图 //矢量服务let imageryProvider new Cesium.WebMapTileServiceImageryProvider({url: "http://t0.tianditu.com/vec_w/wmts?s…

12 mysql char/varchar 的数据存储

前言 这里主要是 由于之前的一个 datetime 存储的时间 导致的问题的衍生出来的探究 探究的主要内容为 int 类类型的存储, 浮点类类型的存储, char 类类型的存储, blob 类类型的存储, enum/json/set/bit 类类型的存储 本文主要 的相关内容是 char 类类型的相关数据的存储 …