当前位置: 首页 > news >正文

使用冒泡排序模拟实现qsort函数

1.冒泡排序

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>int main()
{int arr[] = { 0,2,5,3,4,8,9,7,6,1 };int sz = sizeof(arr) / sizeof(arr[0]);//冒泡排序一共排序 sz-1 趟for (int i = 0; i < sz - 1; ++i){//标志位,如果有序,直接退出int flag = 0;//第一趟比较sz-1次,//以后每趟比较次数-1for (int j = 0; j < sz - 1 - i; ++j){if (arr[j] > arr[j + 1]){flag = 1;int temp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = temp;}}if (!flag)break;}for (int i = 0; i < sz; ++i)printf("%d ", arr[i]);return 0;
}

2.模拟实现

2.1认清障碍

qsort函数可以实现任意数据的排序

但此时的冒泡排序不行,阻碍点:

(1)

冒泡排序中 if 条件判断中的 >

注定了该算法不能实现其他数据的比较

想到:

模仿qsort函数,在冒泡排序内部

调用相关函数实现数据比较

然后根据调用函数的返回值进行后续操作

(2)

上面的交换方式也受到了限制

想到:

需要实现一个

可以实现数据交换的函数

2.2克服障碍

2.2.1依葫芦画瓢

 那就依葫芦画瓢,写下声明

void Bubble_sort(void*base,size_t num,size_t width,int(*cmp)(const void*p1,const void*p2));

此时:

从左往右,要传入的

第一个参数是 待排序数组的第一个元素的地址

 第二个参数是 元素个数

第三个参数是 每个元素的大小,单位是字节

第四个参数是 一个函数指针

Bubble_sort函数通过这个函数指针调用相关的函数

被调用的函数就是用来实现任意数据的比较方式的

被调用的函数:

返回值为int,形参为(const void*p1,const void*p2)

(1

p1指向一个数组元素

p2指向的是p1指向的元素之后的第一个元素

(2)函数内部的要求:

(2.1)void*不能直接解引用或+-整数操作

所以需要根据需求进行相应的显式类型转换

(2.2)显示类型转换后,

当p1指向的内容大于p2时,函数返回 大于0的值

当p1指向的内容小于p2时,函数返回 大于0的值

当p1指向的内容等于p2时,函数返回 0

2.2.2逐步实现

void Bubble_sort(void*base,size_t num,size_t width,int(*cmp)(const void*p1,const void*p2))
{for (int i = 0; i < num - 1; ++i){int flag = 0;for (int j = 0; j < num - 1 - i; ++j){if(){}}if (!flag)break;}
}

冒牌排序外壳:

趟数、比较次数不用改变

2.2.2.1条件判断

if 语句中,根据函数调用返回值进行判断

假设,当当p1指向的内容大于p2时,才进行数据的交换

那么,代码如下:

void Bubble_sort(void*base,size_t num,size_t width,int(*cmp)(const void*p1,const void*p2))
{for (int i = 0; i < num - 1; ++i){int flag = 0;for (int j = 0; j < num - 1 - i; ++j){if(cmp((char*)base+j*width,(char*)base+(j+1)*width)>0){flag = 1;..}}if (!flag)break;}
}

详细解释:

(1)绿色方框框起来的意思是

(1.1)这是两个实参

(1.2)指针指向一种数据时,

总是指向该数据所占空间地址最小的那个字节

(1.3)base接收了数组首元素的地址,但是

我并不知道这是整型、浮点型、字符型的数组

所以我将它强制转换为(char*)类型的指针

这样,无论如何

(char*)base 都指向了数组首元素的第一个字节

(1.4)函数传参传进了width,

注意到:

如果是一个int型的数组

(char*)base 指向了数组首元素第一个字节

(char*)base+width指向了数组第二个元素第一个字节

(char*)base+2*width指向了数组第三个元素的第一个字节

如果是一个char型的数组

(char*)base 指向了数组首元素

(char*)base+width指向了数组第二个元素

(char*)base+2*width指向了数组第三个元素

所以:

实参就是

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

(2)橙色方框框起来的意思是

调用cmp函数

(3)红色方框框起来的意思是

当cmp函数返回值>0时,才进行后续的操作

2.2.2.2交换方式

避免代码冗余,创建一个Swap函数进行数据的交换

void Bubble_sort(void*base,size_t num,size_t width,int(*cmp)(const void*p1,const void*p2))
{for (int i = 0; i < num - 1; ++i){int flag = 0;for (int j = 0; j < num - 1 - i; ++j){if(cmp((char*)base+j*width,(char*)base+(j+1)*width)>0){flag = 1;Swap((char*)base+j*width,(char*)base+(j+1)*width, width);}}if (!flag)break;}
}

(1)我们并不知道元素的类型

但是因为我们知道元素的大小

所以我们可以逐字节地交换两个元素

(2)此时,传入的参数应该是

两个元素的第一个字节、元素的大小

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

内部实现:

void Swap(char* p1, char* p2, size_t width)
{for (int i = 0; i < width; ++i){char temp = *p1;*p1 = *p2;*p2 = temp;p1++;p2++;}
}

(1)width有多大,就交换几次

每次交换后,指针偏移

2.3测试

使用Bubble_sort函数与使用qsort函数一样

需要自己编写一个实现数据比较地函数

这是整型数据的比较

这是字符间的排序 :

注意,元素个数用strlen求!

这是字符串间的排序:

相关文章:

使用冒泡排序模拟实现qsort函数

1.冒泡排序 #define _CRT_SECURE_NO_WARNINGS 1 #include <stdio.h>int main() {int arr[] { 0,2,5,3,4,8,9,7,6,1 };int sz sizeof(arr) / sizeof(arr[0]);//冒泡排序一共排序 sz-1 趟for (int i 0; i < sz - 1; i){//标志位&#xff0c;如果有序&#xff0c;直接…...

AI大模型开发原理篇-4:神经概率语言模型NPLM

神经概率语言模型&#xff08;NPLM&#xff09;概述 神经概率语言模型&#xff08;Neural Probabilistic Language Model, NPLM&#xff09; 是一种基于神经网络的语言建模方法&#xff0c;它将传统的语言模型和神经网络结合在一起&#xff0c;能够更好地捕捉语言中的复杂规律…...

Eigen::Tensor使用帮助

0 引言 用python实现了某些算法之后&#xff0c;想转成C来获取更高的性能。但是python数组的操作太灵活了&#xff0c;尤其是3维、4维、5维等高维数组&#xff0c;以及它们的广播、数组坐标、切片等机制。还有numpy的pad、where等操作更是给C转换带来了更多的麻烦。 查阅了相…...

git基础使用--3---git安装和基本使用

文章目录 git基础使用--3--git-安装和基本使用1. git工具安装1.1 git1.2 TortoiseGit1.3 远程仓2. git本地仓库版本管理2.1 git常用命令2.2 git基本操作2.2.1 设置用户名和邮箱 2.2 git基本操作2.2.1 初始化本地仓 git init2.2.2 查看本地库状态 git status2.2.3 添加暂缓区2.2…...

html的字符实体和颜色表示

在HTML中&#xff0c;颜色可以通过以下几种方式表示&#xff0c;以下是具体的示例&#xff1a; 1. 十六进制颜色代码 十六进制颜色代码以#开头&#xff0c;后面跟随6个字符&#xff0c;每两个字符分别表示红色、绿色和蓝色的强度。例如&#xff1a; • #FF0000&#xff1a;纯红…...

OpenAI发布o3-mini:免费推理模型,DeepSeek引发的反思

引言 在人工智能领域&#xff0c;OpenAI再次引领潮流&#xff0c;推出了全新的推理模型系列——o3-mini。这一系列包括low、medium和high三个版本&#xff0c;旨在进一步推动低成本推理的发展。与此同时&#xff0c;OpenAI的CEO奥特曼也在Reddit的“有问必答”活动中罕见地公开…...

Zemax 中带有体素探测器的激光谐振腔

激光谐振腔是激光系统的基本组成部分&#xff0c;在光的放大和相干激光辐射的产生中起着至关重要的作用。 激光腔由两个放置在光学谐振器两端的镜子组成。一个镜子反射率高&#xff08;后镜&#xff09;&#xff0c;而另一个镜子部分透明&#xff08;输出耦合器&#xff09;。…...

大模型训练(5):Zero Redundancy Optimizer(ZeRO零冗余优化器)

0 英文缩写 Large Language Model&#xff08;LLM&#xff09;大型语言模型Data Parallelism&#xff08;DP&#xff09;数据并行Distributed Data Parallelism&#xff08;DDP&#xff09;分布式数据并行Zero Redundancy Optimizer&#xff08;ZeRO&#xff09;零冗余优化器 …...

C# 实现 “Hello World” 教程

.NET学习资料 .NET学习资料 .NET学习资料 C# 作为一种广泛应用于.NET 开发的编程语言&#xff0c;以其简洁、高效和类型安全等特性&#xff0c;深受开发者喜爱。在踏入 C# 编程领域时&#xff0c;编写经典的 “Hello World” 程序是重要的起点&#xff0c;它能帮助我们快速熟…...

LabVIEW无线齿轮监测系统

本案例介绍了基于LabVIEW的无线齿轮监测系统设计。该系统利用LabVIEW编程语言和改进的天牛须算法优化支持向量机&#xff0c;实现了无线齿轮故障监测。通过LabVIEW软件和相关硬件&#xff0c;可以实现对齿轮箱振动信号的采集、传输和故障识别&#xff0c;集远程采集、数据库存储…...

IM 即时通讯系统-01-概览

前言 有时候希望有一个 IM 工具&#xff0c;比如日常聊天&#xff0c;或者接受报警信息。 其实主要是工作使用&#xff0c;如果是接收报警等场景&#xff0c;其实DD这种比较符合场景。 那么有没有必要再创造一个DD呢&#xff1f; 答案是如果处于个人的私有化使用&#xff0…...

【人工智能】 在本地运行 DeepSeek 模型:Ollama 安装指南

持续更新。。。。。。。。。。。。。。。 【人工智能】 在本地运行 DeepSeek 模型&#xff1a;Ollama 安装指南 安装 Ollama安装 DeepSeek 模型选择版本 &#xff0c;版本越高&#xff0c;参数越多 性能越好使用 DeepSeek 模型 安装 Ollama 访问 Ollama 官网: 前往 https://oll…...

【Linux系统】信号:信号保存 / 信号处理、内核态 / 用户态、操作系统运行原理(中断)

理解Linux系统内进程信号的整个流程可分为&#xff1a; 信号产生 信号保存 信号处理 上篇文章重点讲解了 信号的产生&#xff0c;本文会讲解信号的保存和信号处理相关的概念和操作&#xff1a; 两种信号默认处理 1、信号处理之忽略 ::signal(2, SIG_IGN); // ignore: 忽略#…...

探索 Copilot:开启智能助手新时代

探索 Copilot&#xff1a;开启智能助手新时代 在当今数字化飞速发展的时代&#xff0c;人工智能&#xff08;AI&#xff09;正以前所未有的速度改变着我们的工作和生活方式。而 Copilot 作为一款强大的 AI 助手&#xff0c;凭借其多样的功能和高效的应用&#xff0c;正在成为众…...

解锁豆瓣高清海报(二) 使用 OpenCV 拼接和压缩

解锁豆瓣高清海报(二): 使用 OpenCV 拼接和压缩 脚本地址: 项目地址: Gazer PixelWeaver.py pixel_squeezer_cv2.py 前瞻 继上一篇“解锁豆瓣高清海报(一) 深度爬虫与requests进阶之路”成功爬取豆瓣电影海报之后&#xff0c;本文将介绍如何使用 OpenCV 对这些海报进行智…...

我用Ai学Android Jetpack Compose之Card

这篇学习一下Card。回答来自 通义千问。 我想学习Card&#xff0c;麻烦你介绍一下 当然可以&#xff01;在 Jetpack Compose 中&#xff0c;Card 是一个非常常用的组件&#xff0c;用于创建带有阴影和圆角的卡片式布局。它可以帮助你轻松实现美观且一致的 UI 设计&#xff0c…...

NLP深度学习 DAY4:Word2Vec详解:两种模式(CBOW与Skip-gram)

用稀疏向量表示文本&#xff0c;即所谓的词袋模型在 NLP 有着悠久的历史。正如上文中介绍的&#xff0c;早在 2001年就开始使用密集向量表示词或词嵌入。Mikolov等人在2013年提出的创新技术是通过去除隐藏层&#xff0c;逼近目标&#xff0c;进而使这些单词嵌入的训练更加高效。…...

论文阅读(十):用可分解图模型模拟连锁不平衡

1.论文链接&#xff1a;Modeling Linkage Disequilibrium with Decomposable Graphical Models 摘要&#xff1a; 本章介绍了使用可分解的图形模型&#xff08;DGMs&#xff09;表示遗传数据&#xff0c;或连锁不平衡&#xff08;LD&#xff09;&#xff0c;各种下游应用程序之…...

Python中容器类型的数据(上)

若我们想将多个数据打包并且统一管理&#xff0c;应该怎么办? Python内置的数据类型如序列(列表、元组等)、集合和字典等可以容纳多项数据&#xff0c;我们称它们为容器类型的数据。 序列 序列 (sequence) 是一种可迭代的、元素有序的容器类型的数据。 序列包括列表 (list)…...

PySPARK带多组参数和标签的SparkSQL批量数据导出到S3的程序

设计一个基于多个带标签SparkSQL模板作为配置文件和多组参数的PySPARK代码程序&#xff0c;实现根据不同的输入参数自动批量地将数据导出为Parquet、CSV和Excel文件到S3上&#xff0c;标签和多个参数&#xff08;以“_”分割&#xff09;为组成导出数据文件名&#xff0c;文件已…...

【Linux】shell脚本忽略错误继续执行

在 shell 脚本中&#xff0c;可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行&#xff0c;可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令&#xff0c;并忽略错误 rm somefile…...

Zustand 状态管理库:极简而强大的解决方案

Zustand 是一个轻量级、快速和可扩展的状态管理库&#xff0c;特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...

23-Oracle 23 ai 区块链表(Blockchain Table)

小伙伴有没有在金融强合规的领域中遇见&#xff0c;必须要保持数据不可变&#xff0c;管理员都无法修改和留痕的要求。比如医疗的电子病历中&#xff0c;影像检查检验结果不可篡改行的&#xff0c;药品追溯过程中数据只可插入无法删除的特性需求&#xff1b;登录日志、修改日志…...

376. Wiggle Subsequence

376. Wiggle Subsequence 代码 class Solution { public:int wiggleMaxLength(vector<int>& nums) {int n nums.size();int res 1;int prediff 0;int curdiff 0;for(int i 0;i < n-1;i){curdiff nums[i1] - nums[i];if( (prediff > 0 && curdif…...

苍穹外卖--缓存菜品

1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得&#xff0c;如果用户端访问量比较大&#xff0c;数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据&#xff0c;减少数据库查询操作。 缓存逻辑分析&#xff1a; ①每个分类下的菜品保持一份缓存数据…...

Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)

引言&#xff1a;为什么 Eureka 依然是存量系统的核心&#xff1f; 尽管 Nacos 等新注册中心崛起&#xff0c;但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制&#xff0c;是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...

高防服务器能够抵御哪些网络攻击呢?

高防服务器作为一种有着高度防御能力的服务器&#xff0c;可以帮助网站应对分布式拒绝服务攻击&#xff0c;有效识别和清理一些恶意的网络流量&#xff0c;为用户提供安全且稳定的网络环境&#xff0c;那么&#xff0c;高防服务器一般都可以抵御哪些网络攻击呢&#xff1f;下面…...

Proxmox Mail Gateway安装指南:从零开始配置高效邮件过滤系统

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐&#xff1a;「storms…...

【Linux】自动化构建-Make/Makefile

前言 上文我们讲到了Linux中的编译器gcc/g 【Linux】编译器gcc/g及其库的详细介绍-CSDN博客 本来我们将一个对于编译来说很重要的工具&#xff1a;make/makfile 1.背景 在一个工程中源文件不计其数&#xff0c;其按类型、功能、模块分别放在若干个目录中&#xff0c;mak…...

【前端异常】JavaScript错误处理:分析 Uncaught (in promise) error

在前端开发中&#xff0c;JavaScript 异常是不可避免的。随着现代前端应用越来越多地使用异步操作&#xff08;如 Promise、async/await 等&#xff09;&#xff0c;开发者常常会遇到 Uncaught (in promise) error 错误。这个错误是由于未正确处理 Promise 的拒绝&#xff08;r…...