冒泡排序模拟实现qsort()函数

冒泡排序模拟实现qsort函数

  • 前言
  • 1. 分析
  • 2. 解决一,如何接受不同数据
  • 3. 解决二,如何实现不同数据的比较
  • 4. 解决三,如何实现不同数据交换
  • 5. 模拟bubble_sort()函数排序整型所有代码实现
  • 6. 结构体排序实现
  • 7. 结尾

前言

要模拟qsort()函数,我们首先要知道qsort()函数的特点:

  1. 使用快速排序的方法。
  2. 适用于任何数据类型的排序。

但由于部分学者还没有学习快速排序算法,所以本篇博客采用冒泡排序来模拟功能类似于qsort()的函数bubble_sort。

C库对qsort()函数解释:
在这里插入图片描述

我们得到的关于qsort()函数参数信息:

void qsort(void* base, //指向排序的第一个元素size_t num, //排序元素的个数size_t size,//一个元素的大小,单位为字节int (*cmp)(const void*, const void*)//函数指针类型 — 这个函数指针指向的函数,能够比较base指向数组的两个元素
);

1. 分析

我们首先来看一段普通的冒泡排序来排序整型数据

void bubblr_sort(int arr[], int sz)
{//排序趟数for (int i = 0; i < sz - 1; i++){int tmp = 0;//每趟比较对数for (int j = 0; j < sz - 1 - i; j++){//假设升序,交换元素if (arr[i] > arr[i + 1]){tmp = arr[i];arr[i] = arr[i + 1];arr[i + 1] = tmp;}}}
}
int main()
{int arr[10] = { 10,9,8,7,6,5,4,3,2,1 };int sz = sizeof(arr) / sizeof(arr[0]);bubble_sort(arr, sz);return 0;
}

既然是用冒泡排序来模拟qsort()函数,我们可以以上面这段代码为基础,需改模拟实现。但存在几个问题!!

  1. 如何接受不同的数据类型,而不仅仅是整型。
  2. 对于不同的数据,比如结构体不能简单的用>或<还比较,那如何实现呢?
  3. 对于不同的数据类型,交换略有差异

2. 解决一,如何接受不同数据

void* 是C语言中的通用指针类型,可以指向任意类型的数据。所以我们可以将参数base定义为void*类型指针,来接受不同的数据。

void*用法拓展:

  1. 在使用void* 指针时,因为它不知道指向的类型的大小,需要将其转换为具体的指针类型才能进行操作。例如,可以将void 指针转换为int 指针,然后*对其进行赋值或者解引用操作。
    2. void * 是一个无类型指针,在由于进行算术运算时,需要知道指针指向的具体数据类型的大小以便确定移动的字节数,所以它不能直接进行算术运算。

3. 解决二,如何实现不同数据的比较

由于不同的数据类型有不同的比较方法,我们可以在模拟的bubble_sort()函数参数中添加一个函数指针。将两个元素的比较方法,函数参数的形式进行传递。

Tips:

  • 目前传入的数据以整型为例,所以我们定义比较函数名为cmp_int。在文章结尾将给出传入结构体数据的实现代码。

代码实现

//bubble_sort()实参传入
bubble_sort(arr,sz, sizeof(arr[0]), cmp_int);//bubble_sort()函数参数实现
void bubble_sort(void* base, int num, int size, int (*cmp)(const void*, const void*))//cmp_int函数实现
int cmp_int(const void* p1, const void* p2)
{//强制类型转换为int* ,在进行解引用return (*(int*)p1 - *(int*)p2);//假设升序,则返回>0的数//至于为什么返回这个数据,参考qsort()函数模仿即可
}

4. 解决三,如何实现不同数据交换

对于不同的数据,我们可以交换的两个数的起始地址强制类型转化为(char*),然后计算出两个数据大小,最后两则一个一个字节交换即可。

代码实现

//数据交换我们封装一个Swap()函数
void Swap(char* buf1, char* buf2, int size)//交换arr[i]和arr[i+1]
{char tmp = 0;while (size--){tmp = *buf1;*buf1 = *buf2;*buf2 = tmp;buf1++;buf2++;}
}

5. 模拟bubble_sort()函数排序整型所有代码实现

由于是在冒泡排序的基础上来实现排序的,而排序的趟数和每趟排序的对数是不变的。所有我们只要解决上述问题,将相关代码进行替换即可。

代码实现

#include <stdio.h>int cmp_int(const void* p1, const void* p2)
{return (*(int*)p1 - *(int*)p2);
}void Swap(char* buf1, char* buf2, int size)//交换arr[i]和arr[i+1]
{char tmp = 0;while (size--){tmp = *buf1;*buf1 = *buf2;*buf2 = tmp;buf1++;buf2++;}
}void bubble_sort(void* base, int num, int size, int (*cmp)(const void*, const void*))
{int i = 0;//趟数for (i = 0; i < num; i++){//一趟比较对数//假设升序for (int j = 0; j < num - 1 - i; j++){if (cmp((char*)base + j * size, (char*)base + (j + 1) * size) > 0)//比较两个元素,需要将arr[j]和arr[j+1]的地址传给cmp{//交换Swap((char*)base + j * size, (char*)base + (j + 1) * size, size);}}}
}//测试bubble_sort排序整型数据
void test1()
{int arr[] = { 4,2,5,8,3,8,34,23,1,54 };int sz = sizeof(arr) / sizeof(arr[0]);bubble_sort(arr,sz, sizeof(arr[0]), cmp_int);for (int i = 0; i < sz; i++){printf("%d ", arr[i]);}
}int main()
{test1();return 0;
}

运行结果:
在这里插入图片描述

6. 结构体排序实现

排序结构体时,Swap()和bubble_sort()函数实现是相同的;我们只需要改变以下int_cmp函数即可(注:int_cmp()函数的名字依据比较数据不同,博主命名不同)

代码实现

#include <stdio.h>
#include <string.h>void Swap(char* buf1, char* buf2, int size)//交换arr[i]和arr[i+1]
{char tmp = 0;while (size--){tmp = *buf1;*buf1 = *buf2;*buf2 = tmp;buf1++;buf2++;}
}void bubble_sort(void* base, int num, int size, int (*cmp)(const void*, const void*))
{int i = 0;//趟数for (i = 0; i < num; i++){//一趟比较对数//假设升序for (int j = 0; j < num - 1 - i; j++){//比较两个元素,需要将arr[j]和arr[j+1]的地址传给cmpif (cmp((char*)base + j * size, (char*)base + (j + 1) * size) > 0){//交换Swap((char*)base + j * size, (char*)base + (j + 1) * size, size);}}}
}//测试bubble_sort排序结构体数据
struct Stu
{char name[20];int age;
};int cmp_stu_by_name(const void* p1, const void* p2)
{//比较两个字符时,需要借助函数strcmp()来实现return strcmp(((struct Stu*)p1)->name ,((struct Stu*)p2)->name);
}void test2()
{struct Stu arr[] = { {"zahngsan",20},{"lisi",12},{"wangwu",43} };int sz = sizeof(arr) / sizeof(arr[0]);bubble_sort(arr, sz, sizeof(arr[0]), cmp_stu_by_name);
}int main()
{test2();return 0;
}

运行结果:
在这里插入图片描述

7. 结尾

本篇博客到此就结束了。如果对你有帮助,记得三连哦!感谢您的支持!!

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

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

相关文章

应急管理大屏助力暴雨天气下的水灾防范

随着气候变化和城市化进程的加剧&#xff0c;暴雨天气引发的水灾风险日益凸显。在面对这种自然灾害时&#xff0c;如何高效、及时地应对、减轻损失成为了当务之急。水灾应急管理平台的可视化大屏为相关部门和决策者提供了实时、全面的信息展示和决策支持&#xff0c;大大提升了…

逻辑(css)-背景网格制作(linear-gradient)

目录 linear-gradient需求实现 linear-gradient 语法&#xff1a;linear-gradient([direction], color-stop1, color-stop2, ...) 第一个参数为(可选)方向参数&#xff0c;可以是度数也可以是方位名词,方向与读书的关系如下&#xff1a; 角度方位文字说明示例0degto top从下…

左神算法之中级提升(2)

目录 [案例1】 【题目描述】 【思路解析1】 【思路解析2】 【代码实现】 【案例2】 【题目描述】 【思路解析】 【代码实现】 【案例3】 【题目描述】 【思路解析】 【代码实现】 【案例4】 【题目描述】今日头条2018面试题 第四题 【输入描述】 【思路解析】 【…

零拷贝是如何实现的

零拷贝是如何实现的 零拷贝&#xff08;Zero-copy&#xff09;是一种优化技术&#xff0c;用于在数据传输过程中减少数据的拷贝次数&#xff0c;从而提高数据传输的效率和性能。传统的数据传输涉及多次内存拷贝操作&#xff0c;而零拷贝通过减少或避免这些拷贝操作来实现性能优…

​LeetCode解法汇总​979. 在二叉树中分配硬币

目录链接&#xff1a; 力扣编程题-解法汇总_分享记录-CSDN博客 GitHub同步刷题项目&#xff1a; https://github.com/September26/java-algorithms 原题链接&#xff1a;力扣 描述&#xff1a; 给定一个有 N 个结点的二叉树的根结点 root&#xff0c;树中的每个结点上都对应…

VMware ESXi 7.0 U3n macOS Unlocker OEM BIOS 集成网卡驱动和 NVMe 驱动 (集成驱动版)

VMware ESXi 7.0 U3n macOS Unlocker & OEM BIOS 集成网卡驱动和 NVMe 驱动 (集成驱动版) ESXi 7 U3 标准版集成 Intel 网卡、USB 网卡 和 NVMe 驱动 请访问原文链接&#xff1a;https://sysin.org/blog/vmware-esxi-7-u3-sysin/&#xff0c;查看最新版。原创作品&#x…

力扣 55. 跳跃游戏

题目来源&#xff1a;https://leetcode.cn/problems/jump-game/description/ C题解&#xff08;来源代码随想录&#xff09;&#xff1a;不断更新可覆盖范围&#xff0c;能达到最后一个元素即返回true&#xff0c;否则返回false。 class Solution { public:bool canJump(vecto…

中国移动光猫设置桥接

网上教程五花八门&#xff0c;有些坑有些行&#xff0c;我试成功了&#xff0c;记录一下方法。 一、流程简述 1. 使用超级管理员账号登录中国移动光猫&#xff0c;设置桥接&#xff0c;并重启 2. 用网线连接路由器和光猫&#xff0c;登录路由器&#xff0c;设置宽带拨号&…

【SAP UI5 控件学习】DAY04 Input组Part IV 完结List组Part I

1.时间选择器Time Picker 和Data Picker类似&#xff0c;Time Picker允许用户选择相应的时间。 它有以下一些比较常用的属性。 value用于显示Input中的时间的值&#xff0c;这个属性只能接受字符串的值&#xff0c;如果是UI5.getInstance()获取到的时间&#xff0c;需要转化成…

Linux文件系统概述

本文已收录至《Linux知识与编程》专栏&#xff01; 作者&#xff1a;ARMCSKGT 演示环境&#xff1a;CentOS 7 文件系统概述 前言正文文件与磁盘磁盘介绍与机械硬盘机械硬盘基础结构机械硬盘数据存储与管理 文件操作的细节创建文件访问文件删除文件恢复文件其他情况 最后 前言 …

力扣 279. 完全平方数

一、题目描述 给你一个整数 n&#xff0c;返回和为 n 的完全平方数的最少数量 。 完全平方数是一个整数&#xff0c;其值等于另一个整数的平方&#xff1b;换句话说&#xff0c;其值等于一个整数自乘的积。例如&#xff0c;1、4、9 和 16 都是完全平方数&#xff0c;而 3 和 …

哪款蓝牙耳机通话清楚,几款拥有通话降噪技术的骨传导耳机分享

嘿&#xff0c;你是音乐爱好者吗&#xff1f;还是热衷于锻炼身体&#xff1f;那么你一定不能错过骨传导耳机&#xff01;这种神奇的耳机通过骨头的振动来传递声音&#xff0c;绝不同于传统的耳道或鼓膜传播方式。你可保持对周围环境的警觉&#xff0c;同时避免对你的听力造成任…