用冒泡排序的思想模拟实现Qsort

简介: 用冒泡排序的思想模拟实现Qsort

什么是冒泡排序?

假设这里有一个一维数组

int arr1[10]={0,1,2,3,4,5,6,7,8,9};

我们要对他实现降序排列,

arr1[0]与arr[1]进行比较,如果arr1[0]<arr1[1],那么二者交换位置,即arr1[0]=1,arr1[1]=0.否则不交换位置,继续和下一个元素比较.直到它和最后一个元素比较完.
那么整个冒泡排序一共要经历几次呢?
arr1有10个元素,0要和1 2 3 4 5 6 7 8 9比,1要和2 3 4 5 6 7 8 9比,2要和3 4 5 6 7 8 9比...到8 时,它只用和9比,到9时,就不用比较了,因为9已经和所有元素比较过了。因此比较的次数是元素个数-1.
那么元素内要比较几次呢?
根据上述分析,我们可以知道,每到下一个元素时,比较的次数就-1.

以上就是冒泡排序的基本思想了。

那么使用冒泡排序的qsort到底是如何实现不同类型数据的排序的呢?

在qsort(升序版本)原本的定义中,它会获取数组内两个元素e1、e2的地址,并比较它们的大小,倘若e1-e2>0,那么就会交换e1,e2的值.

这是qsort的参数

 
模仿qsort创建自己的函数
void my_qsort(void* base, size_t sz, size_t width, int(*cmp)(const void* e1, const void* e2))
void* base是用来接受被比较数组的地址的
size_t sz是接受数组元素个数的
int(*cmp)(const void* e1,const void* e2)是用来接受函数指针的
接着是各函数的构建
void swap(char* e1, char* e2,int width)
{
    int i = 0;
    for (i = 0; i < width; i++)//一个字节一个字节的转换,具体取决于width的大小
    {
        char tmp = 0;
        tmp = *e2;
        *e2 = *e1;
        *e1 = tmp;
        e1++;
        e2++;
    }
}
int cmp_int(const void* e1, const void* e2)//这实际上是一个回调函数,my_qsort函数通过调用这个函数,得到一个返回值,再通过这个返回值进行判断是否交换数值
{
    return (*(int*)e1) - (*(int*)e2);
}
int cmp_by_name(const void*e1,const void*e2)
{
    return strcmp((struct stu*)e1,(struct stu*)e2);
    
}
int cmp_by_age(const void* e1, const void* e2)
{
    return ((struct stu*)e1)->age - ((struct stu*)e2)->age;
}
void my_qsort(void* base, size_t sz, size_t width, int(*cmp)(const void* e1, const void* e2))
{
int i=0;
int j=0;
for(i=0;i<sz-1;i++)
{
 for(j=0;j<sz-i-1;j++)
{
   if(cmp((char*)base+j*width,(char*)base+(j+1)*width>0))
        //为什么要将转(char*)以及j和width的用处
        //因为我们无法确认传参进来的指针的类型,因此也就无法确定指针+1的步幅
        //通过width,我们可以确认指针+1的步幅,通过j与j+1,可以得出前后相邻的两地址
            {
               swap((char*)base+j*width,(char*)base+(j+1)*width);
            }
}
}
 
 
 
}
int main()
创建几个不同类型的数组,以便待会测试
{
int arr[10]={5,1,2,6,7,3,8,9,10}
struct stu
{
char name[20];
int age;
}
sturct stu s[3]={{"zhangsan",18},{"lisi",19},{"wangmazi",24}};
    int sz = sizeof(s) / sizeof(s[0]);
    my_qsort(s, sz, sizeof(s[0]), cmp_by_name);//测试不同类型的数组只需传递对应函数的地址即可
}


相关文章
|
3月前
|
人工智能 自然语言处理 安全
OpenClaw 与飞书生态对接指南:企业IM+AI高效集成实操教程
本文为OpenClaw与飞书生态对接的实操指南,涵盖前期筹备(权限、JDK环境、凭证管理)、飞书凭证获取、OpenClaw后台配置、安装包下载排错及常见异常排查,步骤详实、安全规范,助力企业快速实现IM+AI无缝集成。
|
12月前
|
存储 供应链 物联网
RFID鞋服应用大大提升消费者体验感
RFID技术在鞋服行业实现全流程智能化管理,通过电子标签提升商品追踪、库存盘点、防伪防盗效率,优化消费者体验,助力企业数字化转型。
|
缓存 关系型数据库 MySQL
【深入了解MySQL】优化查询性能与数据库设计的深度总结
本文详细介绍了MySQL查询优化和数据库设计技巧,涵盖基础优化、高级技巧及性能监控。
2130 1
|
人工智能 编解码 自然语言处理
Gemma3:Google开源多模态神器,轻量高效,精通140+语言,解锁文本与图像任务
在当今快速发展的 AI 领域,多模态模型正逐渐成为推动技术革新的重要力量。Google 最新推出的 Gemma 3 模型,凭借其轻量级、多模态的特性,为文本生成和图像理解任务带来了全新的可能性。它不仅支持文本和图像输入,还具备强大的语言处理能力,覆盖超过 140 种语言,并且能够在资源有限的设备上高效运行。从问答到摘要,从推理到图像分析,Gemma 3 正在重新定义 AI 模型的边界,为开发者和研究人员提供了一个极具潜力的工具。
1257 0
|
前端开发 JavaScript Java
基于Java+Springboot+Vue开发的口腔牙科诊所预约管理系统
基于Java+Springboot+Vue开发的口腔牙科诊所预约管理系统(前后端分离),这是一项为大学生课程设计作业而开发的项目。该系统旨在帮助大学生学习并掌握Java编程技能,同时锻炼他们的项目设计与开发能力。通过学习基于Java的口腔预约管理系统项目,大学生可以在实践中学习和提升自己的能力,为以后的职业发展打下坚实基础。
740 2
基于Java+Springboot+Vue开发的口腔牙科诊所预约管理系统
|
JSON API 开发者
京东店铺所有商品数据接口(JD.item_search_shop)丨京东API接口指南
JD.item_search_shop 是京东开放平台提供的接口,用于获取店铺所有商品数据。请求方法为 GET,主要参数包括 shopId(必填)、page、pageSize 和 sortType。开发者需先注册并获取 API 密钥,确定目标店铺 ID 后构建请求。响应为 JSON 格式,适用于电商应用、价格比较和市场分析等场景。
1344 0
|
弹性计算 数据安全/隐私保护
如何修改和重置阿里云服务器的远程连接密码(图文教程)?
如果在创建实例时没有设置密码,或者密码丢失,您可以在控制台上重新设置实例的登录密码。本文仅描述如何在 ECS 管理控制台上修改实例登录密码。
|
索引
汉字编码对照表(gb2312/unicode/utf8)
一、汉字编码的种类     汉字编码中现在主要用到的有三类,包括GBK,GB2312和Big5。     1、GB2312又称国标码,由国家标准总局发布,1981年5月1日实施,通行于大陆。
6711 0
|
SQL 开发框架 缓存
【Entity Framework】 EF中DbContext类详解
【Entity Framework】 EF中DbContext类详解
664 0
|
Kubernetes Cloud Native 开发工具
云原生|kubernetes|helm3 自定义离线安装部署ingress-nginx
云原生|kubernetes|helm3 自定义离线安装部署ingress-nginx
1193 0