用 C 语言实现通用的冒泡排序算法

在日常编程中,排序算法是一个非常常见且重要的工具。虽然有许多排序算法可以选择,但如果你需要一个能够处理不同数据类型的排序算法,如何设计一个通用的排序算法呢?今天我们将实现一个通用的冒泡排序算法,支持不同数据类型的排序,并且使用函数指针来提供灵活的比较方式。

1. 冒泡排序算法简介

冒泡排序是一种简单的排序算法,其工作原理是通过不断交换相邻元素,使得每次遍历都能将最大的元素“冒泡”到数组的末端。它的时间复杂度是 O(n²),虽然不适合排序大数据量的情况,但由于实现简单,它仍然是学习排序算法时非常有用的工具。

2. 通用冒泡排序的实现思路

我们要实现一个通用的冒泡排序,即可以处理任意类型的数组(整数、浮点数、字符串等)。为了实现这一点,我们需要考虑以下几个要点:

  • 类型无关性:使用 void * 来表示数组元素,这样可以让函数支持处理任意类型的数据。
  • 比较函数:使用函数指针来允许用户定义比较逻辑,确保排序可以根据用户的需求进行。
  • 内存操作:我们将使用 memcpy 来交换数组元素,这样可以处理任意大小的元素。

3. 代码实现

#include <stdio.h>
#include <stdlib.h>
#include <string.h>// 通用比较函数的类型
typedef int (*CompareFunc)(const void *, const void *);// 通用冒泡排序函数
void bubbleSort(void *base, size_t num, size_t size, CompareFunc compare) {unsigned char *arr = (unsigned char *)base;for (size_t i = 0; i < num - 1; i++) {int swapped = 0;for (size_t j = 0; j < num - i - 1; j++) {unsigned char *a = arr + j * size;unsigned char *b = arr + (j + 1) * size;if (compare(a, b) > 0) {unsigned char temp[size];memcpy(temp, a, size);memcpy(a, b, size);memcpy(b, temp, size);swapped = 1;}}if (!swapped) {break;}}
}// 示例比较函数:用于排序整数
int compareInt(const void *a, const void *b) {return (*(int *)a - *(int *)b);
}// 示例比较函数:用于排序浮点数
int compareFloat(const void *a, const void *b) {if (*(float *)a < *(float *)b) return -1;if (*(float *)a > *(float *)b) return 1;return 0;
}// 打印数组的函数
void printArray(void *base, size_t num, size_t size, void (*printElem)(const void *)) {unsigned char *arr = (unsigned char *)base;for (size_t i = 0; i < num; i++) {printElem(arr + i * size);}printf("\n");
}// 打印整数数组元素
void printInt(const void *a) {printf("%d ", *(int *)a);
}// 打印浮点数数组元素
void printFloat(const void *a) {printf("%.2f ", *(float *)a);
}int main() {// 测试整数数组int arrInt[] = {64, 34, 25, 12, 22, 11, 90};size_t numInt = sizeof(arrInt) / sizeof(arrInt[0]);printf("排序前的整数数组: ");printArray(arrInt, numInt, sizeof(int), printInt);bubbleSort(arrInt, numInt, sizeof(int), compareInt);printf("排序后的整数数组: ");printArray(arrInt, numInt, sizeof(int), printInt);// 测试浮点数数组float arrFloat[] = {64.5, 34.2, 25.1, 12.9, 22.7, 11.6, 90.3};size_t numFloat = sizeof(arrFloat) / sizeof(arrFloat[0]);printf("排序前的浮点数数组: ");printArray(arrFloat, numFloat, sizeof(float), printFloat);bubbleSort(arrFloat, numFloat, sizeof(float), compareFloat);printf("排序后的浮点数数组: ");printArray(arrFloat, numFloat, sizeof(float), printFloat);return 0;
}

代码解析

  1. bubbleSort 函数

    • 我们使用 void *base 来表示数组指针,使得这个函数能够处理不同类型的数组。
    • size_t size 表示每个元素的大小,CompareFunc compare 是一个函数指针,允许用户传入自定义的比较函数。
    • 在排序过程中,我们通过 memcpy 来交换元素,因为 void * 是不确定类型的指针,直接操作可能会出错。
  2. compareIntcompareFloat 函数

    • compareInt 函数用于比较整数,compareFloat 函数用于比较浮点数。你可以根据需要,定义更多的比较函数来支持其他数据类型。
  3. printArray 函数

    • 该函数用于打印数组,支持任何类型的元素。通过传入打印函数 printElem,我们可以根据不同的数据类型打印不同的元素。

示例输出

排序前的整数数组: 64 34 25 12 22 11 90 
排序后的整数数组: 11 12 22 25 34 64 90 
排序前的浮点数数组: 64.50 34.20 25.10 12.90 22.70 11.60 90.30 
排序后的浮点数数组: 11.60 12.90 22.70 25.10 34.20 64.50 90.30 

4. 总结

本文实现了一个通用的冒泡排序函数,支持对任意类型的数组进行排序。通过使用 void * 指针和函数指针,我们使得排序函数具有很好的灵活性和可扩展性。无论是整数、浮点数还是其他类型的数组,只需要提供合适的比较函数,就可以轻松进行排序。

这种通用的排序实现方式,可以在很多场景中得到应用,特别是在处理不同类型数据的库函数中。如果你正在开发一个库,并且需要支持不同类型的数据,类似的实现方式会非常有用。

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

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

相关文章

C# 变量全解析:声明、初始化与使用

在多用途的编程语言中&#xff0c;程序存取数据是一项基础且关键的功能&#xff0c;而这一功能主要通过变量来实现。本文将全面深入地探讨 C# 中的变量&#xff0c;包括变量的种类、声明、初始化、自动初始化、多变量声明以及如何使用变量的值。 变量概述 变量是一个名称&…

Dify中的文本分词处理技术详解

Dify中的文本分词处理技术详解 引言核心架构概览索引处理器工厂 文本分词技术详解基础分词器增强型递归字符分词器固定分隔符文本分词器递归分割算法 索引处理器中的分词应用特殊索引处理器的分词特点问答索引处理器父子索引处理器 分词技术的应用场景技术亮点与优势总结 引言 …

如何打包python程序为可执行文件

将 Python 程序打包为可执行文件是一个常见需求&#xff0c;尤其是在希望将应用程序分享给不具备 Python 环境的用户时。以下是使用 PyInstaller 工具将 Python 程序打包为可执行文件的步骤。 步骤 1&#xff1a;安装 PyInstaller 如果您还没有安装 PyInstaller&#xff0c;请…

美团Java后端二面面经!

场景题是面试的大头&#xff0c;建议好好准备 Q. [美团]如何设计一个外卖订单的并发扣减库存系统&#xff1f; Q.[美团]为啥初始标记和重新标记需要STW&#xff1f; Q.[美团]骑手位置实时更新&#xff0c;如何保证高并发写入&#xff1f; Q.[美团]订单表数据量过大导致查询…

在应用运维过程中,业务数据修改的证据留存和数据留存

在应用运维过程中,业务数据修改的证据留存和数据留存至关重要,以下是相关介绍: 一、证据留存 操作日志记录 : 详细记录每一次业务数据修改的操作日志,包括操作人员、操作时间、修改内容、修改前后数据的对比等。例如,某公司业务系统中,操作日志会精确记录员工小张在 2…

Eigen迭代求解器类

1. 迭代求解器核心类概览 Eigen 提供多种迭代法求解稀疏线性方程组 AxbAxb&#xff0c;适用于大规模稀疏矩阵&#xff1a; 求解器类适用矩阵类型算法关键特性ConjugateGradient对称正定&#xff08;SPD&#xff09;共轭梯度法&#xff08;CG&#xff09;高精度&#xff0c;内…

ORACLE数据库备份入门:第四部分:2-备份场景举例

下面以4个常见的场景为例&#xff0c;介绍如何规划备份方案。备份方案没有标准答案&#xff0c;需要根据实现情况来制定&#xff0c;也和管理员的个人使用习惯有很大相关性。 1 交易型数据库备份 以银行的交易系统为例&#xff0c;除了前一章节提到的关于RPO和RTO的指标外&am…

小白如何学会完整挪用Github项目?(以pix2pix为例)

[目录] 0.如何完整地复现/应用一个Github项目 1.建立适用于项目的环境 2.数据准备与模型训练阶段 3.训练过程中的一些命令行调试必备知识0.如何完整地复现/应用一个Github项目 前日在健身房的组间同一位好友交流时&#xff0c;得到了一个一致结论—— ** Github \texttt{Githu…

蓝桥杯 5. 交换瓶子

交换瓶子 原题目链接 题目描述 有 N 个瓶子&#xff0c;编号为 1 ~ N&#xff0c;放在架子上。 例如有 5 个瓶子&#xff0c;当前排列为&#xff1a; 2 1 3 5 4每次可以拿起 2 个瓶子&#xff0c;交换它们的位置。 要求通过若干次交换&#xff0c;使得瓶子的编号从小到大…

Linux 系统渗透提权

Linux 系统渗透提权 比赛题库-Linux 系统渗透提权 文章目录 Linux 系统渗透提权比赛题库-Linux 系统渗透提权 前言一、解题过程1.使用渗透机对服务器信息收集&#xff0c;并将服务器中 SSH 服务端口号作为 flag 提 交&#xff1b;2.使用渗透机对服务器信息收集&#xff0c;并将…

华为OD机试真题——查找接口成功率最优时间段(2025A卷:100分)Java/python/JavaScript/C/C++/GO最佳实现

2025 A卷 100分 题型 本专栏内全部题目均提供Java、python、JavaScript、C、C、GO六种语言的最佳实现方式&#xff1b; 并且每种语言均涵盖详细的问题分析、解题思路、代码实现、代码详解、3个测试用例以及综合分析&#xff1b; 本文收录于专栏&#xff1a;《2025华为OD真题目录…

华为OD机试真题——绘图机器(2025A卷:100分)Java/python/JavaScript/C++/C/GO最佳实现

2025 A卷 100分 题型 本文涵盖详细的问题分析、解题思路、代码实现、代码详解、测试用例以及综合分析&#xff1b; 并提供Java、python、JavaScript、C、C语言、GO六种语言的最佳实现方式&#xff01; 本文收录于专栏&#xff1a;《2025华为OD真题目录全流程解析/备考攻略/经验…

基于 Python(selenium) 的百度新闻定向爬虫:根据输入的关键词在百度新闻上进行搜索,并爬取新闻详情页的内容

该项目能够根据输入的关键词在百度新闻上进行搜索,并爬取新闻详情页的内容。 一、项目准备 1. 开发环境配置 操作系统:支持 Windows、macOS、Linux 等主流操作系统,本文以 Windows 为例进行说明。Python 版本:建议使用 Python 3.8 及以上版本,以确保代码的兼容性和性能。…

MySQL表的操作 -- 表的增删改查

目录 1. 表的创建2. 表的查看3. 表的修改4. 表的删除5. 总结 1. 表的创建 1.查看字符集及效验规则 2. 表的创建 CREATE TABLE table_name ( field1 datatype, field2 datatype, field3 datatype ) character set 字符集 collate 校验规则 engine 存储引擎;创建用户表1 创建用…

如何解决极狐GitLab 合并冲突?

极狐GitLab 是 GitLab 在中国的发行版&#xff0c;关于中文参考文档和资料有&#xff1a; 极狐GitLab 中文文档极狐GitLab 中文论坛极狐GitLab 官网 合并冲突 (BASIC ALL) 合并冲突发生在合并请求的两个分支&#xff08;源分支和目标分支&#xff09;对相同代码行进行了不同…

oracle不同数据库版本的自增序列

-- 查看数据库版本 SELECT * FROM v$version WHERE banner LIKE Oracle%; 1. Oracle 12c及以上版本支持 id NUMBER GENERATED ALWAYS AS IDENTITY PRIMARY KEY, id NUMBER GENERATED ALWAYS AS IDENTITY (START WITH 1 INCREMENT BY 1) PRIMARY KEY, -- 语法 id NUMBER GENER…

VIC-3D非接触全场应变测量系统用于小尺寸测量之电子元器件篇—研索仪器DIC数字图像相关技术

在5G通信、新能源汽车电子、高密度集成电路快速迭代的今天&#xff0c;电子元件的尺寸及连接工艺已进入亚毫米级竞争阶段&#xff0c;这种小尺寸下的力学性能评估对测量方式的精度有更高的要求&#xff0c;但传统应变测量手段常因空间尺寸限制及分辨率不足难以捕捉真实形变场。…

pod 创建私有库指南

步骤 参考&#xff1a;iOS Pod 私有库创建指南-百度开发者中心 下面主要是对参考链接里面的解释&#xff1a; 创建两个仓库&#xff1a; 一个叫podframe.git&#xff0c;用来存放自定义的framework&#xff0c;比如TestPodFrame.framework一个叫podspec.git&#xff0c;用来…

【JavaEE】Spring AOP的注解实现

目录 一、AOP 与 Spring AOP二、Spring AOP简单实现三、详解Spring AOP3.1 Spring AOP 核心概念3.1.1 切点&#xff08;Pointcut&#xff09;3.1.2 连接点&#xff08;Join Point&#xff09;3.1.3 通知&#xff08;Advice&#xff09;3.1.4 切面&#xff08;Aspect&#xff09…

协作开发攻略:Git全面使用指南 — 结语

协作开发攻略&#xff1a;Git全面使用指南 — 结语 Git 是一种分布式版本控制系统&#xff0c;用于跟踪文件和目录的变更。它能帮助开发者有效管理代码版本&#xff0c;支持多人协作开发&#xff0c;方便代码合并与冲突解决&#xff0c;广泛应用于软件开发领域。 文中内容仅限技…