冒泡排序与其C语言通用连续类型排序代码
冒泡排序与其C语言通用连续类型排序代码
- 冒泡排序
- 冒泡排序为交换排序的一种:
- 动图展示:
- 冒泡排序的特性总结:
- 冒泡排序排整型数据参考代码(VS2022C语言环境):
- 冒泡排序C语言通用连续类型排序代码
- 对比较的方式更改:
- 对交换的方式更改:
- 结果验证:
- 内置类型:
- 自定义类型:
- 注意:
冒泡排序
冒泡排序为交换排序的一种:
- 基本思想:所谓交换,就是根据序列中两个记录键值的比较结果来对换这两个记录在序列中的位置。
- 交换排序的特点是:将键值较大的记录向序列的尾部移动,键值较小的记录向序列的前部移动。
而冒泡排序升序时每遍历一次会将未排好的集合中大的值移动到后面(或小的移到前面),直到排好序。
动图展示:

冒泡排序的特性总结:
- 冒泡排序是一种非常容易理解的排序
- 时间复杂度:O(N ^ 2)
- 空间复杂度:O(1)
- 稳定性:稳定
冒泡排序排整型数据参考代码(VS2022C语言环境):
#include <stdio.h>
#include <stdbool.h>void swap(int* a, int* b)
{int temp = *a;*a = *b;*b = temp;
}// 要排序的数组 数组大小
int bubbleSort(int* arr, int sz)
{// 1.n个数中,每次交换前需要比较两个数字,则比较次数为n - 1for (int i = 0; i < sz - 1; ++i){bool flag = true; // 3.检查是否有序// 2.在 “1.” 的基础之上,i每循环一次,必定有一个数排好到后面,则 “- i" 来优化for (int j = 0; j < sz - 1 - i; ++j){if (arr[j] > arr[j + 1]){flag = false; // 3.表示无序swap(&arr[j], &arr[j + 1]);}}if (flag == true) // 3.有序直接退出循环{break;}}
}int main()
{int arr[10] = { 3, 9, 2, 7, 8, 5, 6, 1, 10, 4 };int sz = 10;bubbleSort(arr, sz);for (int i = 0; i < sz; ++i){printf("%d ", arr[i]);}return 0;
}
冒泡排序C语言通用连续类型排序代码
上述C语言冒泡排序代码只支持整型排序,这里将其扩展为通用的连续类型排序代码。
参考C语言内置的qsort排序:

可以得到函数为:

void swap(char* a, char* b, size_t width)
{for (int i = 0; i < width; ++i){char temp = *(a + i);*(a + i) = *(b + i);*(b + i) = temp;}
}// 要排序的数组 数组大小 每个元素宽度 比较的函数指针
int bubbleSort(void* base, size_t sz, size_t width, int (*compare)(const void* e1, const void* e2))
{// 1.n个数中,每次交换前需要比较两个数字,则比较次数为n - 1for (int i = 0; i < sz - 1; ++i){bool flag = true; // 3.检查是否有序// 2.在 “1.” 的基础之上,i每循环一次,必定有一个数排好到后面,则 “- i" 来优化for (int j = 0; j < sz - 1 - i; ++j){if (compare((char*)base + j * width, (char*)base + j * width + width) > 0){flag = false; // 3.表示无序swap((char*)base + j * width, (char*)base + j * width + width, width);}}if (flag == true) // 3.有序直接退出循环{break;}}
}
事实上,我们只需要对其两个地方大幅度更改,就可以得到通用的排序:
对比较的方式更改:
将比较方式改为函数指针的方式,这样使用者使用时可以自己写比较的类型函数(不仅包含内置类型,struct 定义的也可以,但前提是连续的)


如果使用者对整型排序,则自己写的compare为(只供参考,方法不唯一):
int cmp(const void* e1, const void* e2)
{// (int*)e1 表示将泛型指针转为整型指针// *((int*)e1) 表示对整型指针解引用从而得到整型的数 // 两整型的数相减,为正则e1大,为负则e2大,为0则相等return *((int*)e1) - *((int*)e2);
}
对交换的方式更改:
这里只需将交换方式改为一个字节一个字节的方式交换即可。


则swap应改为:
void swap(char* a, char* b, size_t width)
{// a 和 b 表示两个数开始的地址// a + i 表示 a 元素第 i 块字节的地址,同理于b// *(a + i) 表示 a 元素第 i 块字节的内容,同理于b// 通过一个字节一个字节的交换,确保内容不会丢失for (int i = 0; i < width; ++i){char temp = *(a + i);*(a + i) = *(b + i);*(b + i) = temp;}
}
结果验证:
内置类型:


完整代码:
#include <stdio.h>
#include <stdbool.h>void swap(char* a, char* b, size_t width)
{for (int i = 0; i < width; ++i){char temp = *(a + i);*(a + i) = *(b + i);*(b + i) = temp;}
}// 要排序的数组 数组大小 每个元素宽度 比较的函数指针
int bubbleSort(void* base, size_t sz, size_t width, int (*compare)(const void* e1, const void* e2))
{// 1.n个数中,每次交换前需要比较两个数字,则比较次数为n - 1for (int i = 0; i < sz - 1; ++i){bool flag = true; // 3.检查是否有序// 2.在 “1.” 的基础之上,i每循环一次,必定有一个数排好到后面,则 “- i" 来优化for (int j = 0; j < sz - 1 - i; ++j){if (compare((char*)base + j * width, (char*)base + j * width + width) > 0){flag = false; // 3.表示无序swap((char*)base + j * width, (char*)base + j * width + width, width);}}if (flag == true) // 3.有序直接退出循环{break;}}
}int cmp(const void* e1, const void* e2) // 对整形
{return *((int*)e1) - *((int*)e2);
}int cmp1(const void* e1, const void* e2) // 对字符
{return *((char*)e1) - *((char*)e2);
}int cmp2(const void* e1, const void* e2) // 对浮点
{double num1 = *(double*)e1;double num2 = *(double*)e2;// double 返回与 int 冲突会影响,只需更改一下返回逻辑return num1 > num2 ? 1 : -1;
}int main()
{int arr[10] = { 3, 9, 2, 7, 8, 5, 6, 1, 10, 4 };int sz = 10;bubbleSort(arr, sz, sizeof(int), cmp);for (int i = 0; i < sz; ++i){printf("%d ", arr[i]);}printf("\n");char arr1[10] = { 3, 9, 2, 7, 8, 5, 6, 1, 10, 4 };double arr2[10] = { 3.1, 9.4, 2.9, 7.8, 8.8, 5.1, 6.2, 1.0, 10.1, 4.4 };bubbleSort(arr1, sz, sizeof(char), cmp1);bubbleSort(arr2, sz, sizeof(double), cmp2);for (int i = 0; i < sz; ++i){printf("%d ", arr1[i]);}printf("\n");for (int i = 0; i < sz; ++i){printf("%.2lf ", arr2[i]);}printf("\n");return 0;
}
自定义类型:


完整代码:
#include <stdio.h>
#include <stdbool.h>
#include <string.h>void swap(char* a, char* b, size_t width)
{for (int i = 0; i < width; ++i){char temp = *(a + i);*(a + i) = *(b + i);*(b + i) = temp;}
}// 要排序的数组 数组大小 每个元素宽度 比较的函数指针
int bubbleSort(void* base, size_t sz, size_t width, int (*compare)(const void* e1, const void* e2))
{// 1.n个数中,每次交换前需要比较两个数字,则比较次数为n - 1for (int i = 0; i < sz - 1; ++i){bool flag = true; // 3.检查是否有序// 2.在 “1.” 的基础之上,i每循环一次,必定有一个数排好到后面,则 “- i" 来优化for (int j = 0; j < sz - 1 - i; ++j){if (compare((char*)base + j * width, (char*)base + j * width + width) > 0){flag = false; // 3.表示无序swap((char*)base + j * width, (char*)base + j * width + width, width);}}if (flag == true) // 3.有序直接退出循环{break;}}
}typedef struct Student
{char name[20];int age;char id[10];
} Student;int cmpAge(const void* e1, const void* e2)
{return ((Student*)e1)->age - ((Student*)e2)->age;
}int cmpId(const void* e1, const void* e2)
{return strcmp(((Student*)e1)->id, ((Student*)e2)->id);
}int main()
{Student arr[5] = {{.name = "张三", .age = 20, .id = "1" },{.name = "李四", .age = 21, .id = "2" },{.name = "王二", .age = 18, .id = "3" },{.name = "麻子", .age = 30, .id = "4" } };int sz = 4;bubbleSort(arr, sz, sizeof(Student), cmpAge);printf("以年龄排序:\n");for (int i = 0; i < sz; ++i){printf("%s ", arr[i].name);printf("%d ", arr[i].age);printf("%s\n", arr[i].id);}printf("\n");bubbleSort(arr, sz, sizeof(Student), cmpId);printf("以ID排序:\n");for (int i = 0; i < sz; ++i){printf("%s ", arr[i].name);printf("%d ", arr[i].age);printf("%s\n", arr[i].id);}printf("\n");return 0;
}
注意:
上述代码对不连续的数据无效,如链表的每个元素是以指针连接存储的,compare函数 和 swap函数 需要更改来解决。
相关文章:
冒泡排序与其C语言通用连续类型排序代码
冒泡排序与其C语言通用连续类型排序代码 冒泡排序冒泡排序为交换排序的一种:动图展示:冒泡排序的特性总结:冒泡排序排整型数据参考代码(VS2022C语言环境): 冒泡排序C语言通用连续类型排序代码对比较的方式更…...
Python爬虫并输出
1. Python爬虫并输出示例 下面是一个使用Python编写的简单网络爬虫示例,该爬虫将抓取某个网页(例如,我们假设为https://example.com,但请注意实际使用时我们需要替换为一个真实且允许抓取的网站)的标题(Ti…...
交叉熵损失函数的使用目的(很肤浅的理解)
第一种使用方法 import torch from torch import nn # Example of target with class indices loss nn.CrossEntropyLoss() input torch.randn(3, 5, requires_gradTrue) target torch.empty(3, dtypetorch.long).random_(5) output loss(input, target) output.backward(…...
MySQL:TABLE_SCHEMA及其应用
MySQL TABLE_SCHEMA及其应用 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite:http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this article:https://blog.csdn.net/qq_28550263/ar…...
【MySQL】4.MySQL 的数据类型
MySQL 的数据类型 一.数据类型分类在这里插入图片描述二.注意点1.char VS varchar2.datetime VS timestamp3.enum 和 set 的使用方法 一.数据类型分类 二.注意点 1.char VS varchar char 的意义是直接开辟固定大小的空间,浪费磁盘空间,但是效率高varcha…...
STM32中断(NVIC和EXIT)
CM3 内核支持 256 个中断,其中包含了 16 个内核中断和 240个外部中断,并且具有 256 级的可编程中断设置。但STM32 并没有使用CM3内核的全部东西,而是只用了它的一部分。STM32有 76 个中断,包括16 个内核中断和 60 个可屏蔽中断&am…...
哈弗架构和冯诺伊曼架构
文章目录 1. 计算机体系结构 2. 哈弗架构(Harvard Architecture) 3. 改进的哈弗架构 4. 冯诺伊曼架构(Von Neumann Architecture) 5. 结构对比 1. 计算机体系结构 计算机体系结构是指计算机系统的组织和实现方式,…...
Python实现动态迷宫生成:自动生成迷宫的动画
文章目录 引言准备工作前置条件 代码实现与解析导入必要的库初始化Pygame定义迷宫生成类主循环 完整代码 引言 迷宫生成算法在游戏开发和图形学中有着广泛的应用。它不仅可以用于创建迷宫游戏,还可以用于生成有趣的图案。在这篇博客中,我们将使用Python…...
大学生暑假“三下乡”社会实践工作新闻投稿指南请查收!
近年来,大学生暑期“三下乡”社会实践工作方兴未艾,越来越多的大学生通过参与“三下乡”实践工作,走出校园,深入基层,体验农村生活,服务农民,促进农村经济社会发展,实现了理论与实践…...
MySQL InnoDB存储引擎
MySQL InnoDB存储引擎 InnoDB 存储引擎的优点:由于 InnoDB 存储引擎存储的数据量大,性能高,可以有效的保证数据安全等优点,在 MySQL 5.5 后称为了默认的存储引擎。 InnoDB 内存结构: 缓冲池(buffer poll&…...
无头单向非循环链表实现 and leetcode刷题
无头单向非循环链表实现 1. 单链表的模拟实现IList.java接口:MySingleList.java文件: 2. leetcode刷题2.1 获取链表的中间节点2.2 删除链表中所有值为value的元素2.3 单链表的逆置2.4 获取链表倒数第k个节点2.5 给定 x, 把一个链表整理成前半部分小于 x,…...
Ubuntu系统上安装Apache和WordPress
** 第一步跟新系统包 ** 首先跟新系统包 sudo apt update sudo apt upgrade第二步下载安装apache sudo apt install apache2 ##查看apache的状态是否启动成功 sudo systemctl status apache2 ##查看服务器的ip地址 sudo ip a通过ip地址进行访问apache页面 第三步下载安装…...
Doze和AppStandby白名单配置方法和说明
机制 配置路径 配置案例 说明 影响机制 调试命令 Doze /platform/frameworks/base /data/etc/platform.xml allow-in-power-save 【系统应用Doze白名单配置】 Doze\Job\AppStandby\Alarm\WakeLock\Sync 查看Doze白名单:adb shell dumpsys deviceidle 添加Doze白名单…...
坑2.Date类型的请求参数
前端 <el-form-item label"结束日期" prop"endTime"><el-date-pickerv-model"dataForm.endTime"type"date"value-format"yyyy-MM-dd HH:mm:ss"placeholder"选择日期"></el-date-picker></el…...
javaweb ajax maven mybatis spring springmvc 在项目中有什么用, 举例说明
JavaWeb是一种基于Java语言的Web开发技术,可以用来开发动态网站和Web应用程序。 AJAX(Asynchronous JavaScript and XML)是一种在Web开发中用于实现异步通信的技术,可以在不刷新整个网页的情况下更新部分页面内容,提升…...
Python编程学习笔记(4)--- 字典
目录 1 什么是字典 2 使用字典 2.1 访问字典中的值 2.2 添加键值对 2.3 创建空字典 2.4 修改字典中的值 2.5 删除键值对 2.6 类似键值对组成的字典 2.7 使用get()来访问值 3 遍历字典 3.1 遍历所有键值对 3.2 遍历字典中的所有键 3.3 按照特…...
会员运营体系设计及SOP梳理
一些做会员的经验和方法分享给大家,包括顶层思考、流程的梳理、组织的建立,后续会做成系列,最近几期主要围绕顶层策略方面,以下是核心内容的整理: 1、会员运营体系设计 顶层设计与关键业务定位:建立客户运营…...
SQL 自定义函数
概念 自定义函数是用户根据自己的业务逻辑或计算需求创建的函数。这些函数可以接收一个或多个输入参数,执行一系列的操作(如计算、数据处理、逻辑判断等),并最终返回一个值或结果集。自定义函数可以被多次重用,提高了…...
C# 下sendmessage和postmessage的区别详解与示例
文章目录 1、SendMessage2、PostMessage3、两者的区别: 总结 在C#中,SendMessage和PostMessage是两个用于Windows编程的API,它们用于向窗口发送消息。这两个方法都位于System.Windows.Forms命名空间中,通常用于自动化Windows应用程…...
Transformer重要论文与书籍 - Transformer教程
近年来,人工智能领域中的Transformer模型无疑成为了炙手可热的研究对象。从自然语言处理(NLP)到计算机视觉,Transformer展现出了前所未有的强大能力。今天,我们将探讨Tra在当今的人工智能和机器学习领域,Tr…...
AI大模型大数据隐私安全解决方案
随着人工智能技术飞速迭代,大模型训练、精调与推理愈发依赖海量数据,云上环境的便捷性也让数据隐私保护面临严峻挑战。AI大模型数据处理全流程包含大量敏感信息,一旦泄露、篡改或滥用,将损害用户权益、引发合规风险与信任危机。因…...
Cursor AI助手反馈插件:用点赞点踩调教你的编程伙伴
1. 项目概述:一个为开发者“减负”的智能工具如果你是一名开发者,尤其是深度使用 Cursor 这类 AI 编程助手的,大概率遇到过这样的场景:你写了一段代码,AI 助手(比如 Cursor 的 Copilot)给出了一…...
【限时开放】NotebookLM气候专项Prompt Library(含AR6 WGII章节级语义索引模板):仅向高校科研组开放72小时
更多请点击: https://codechina.net 第一章:NotebookLM气候研究辅助概述 NotebookLM 是 Google 推出的基于人工智能的文档理解与推理工具,专为研究人员设计,支持上传 PDF、TXT 等格式的学术文献、观测报告及政策文件,…...
数学科研效率提升300%,NotebookLM辅助建模全流程解析,含独家提示词矩阵与误差校验协议
更多请点击: https://intelliparadigm.com 第一章:NotebookLM数学研究辅助的范式革命 传统数学研究长期依赖纸笔推演、孤立文献查阅与手工公式验证,而NotebookLM通过其独特的“语义锚点双文档协同推理”机制,重构了从问题建模到定…...
[实践|鸿蒙] 从HAP到APP:DevEco Studio编译构建全流程实战解析
1. 鸿蒙应用构建基础:理解HAP与APP的关系 第一次接触鸿蒙应用开发时,我被HAP和APP这两个概念搞得有点懵。经过几个项目的实战,终于搞明白了它们的关系。简单来说,HAP(Harmony Ability Package)就像乐高积木…...
Ghost区块链集成:NFT内容所有权与分发方案
Ghost区块链集成:NFT内容所有权与分发方案 内容创作者的数字版权困境 传统内容发布平台存在严重的数字版权问题:文章被随意转载、原创收益被平台抽成、作品归属权难以证明。根据2024年《数字内容版权报告》,78%的独立创作者曾遭遇内容侵权&…...
AMD Ryzen处理器底层调试技术解析:SMUDebugTool的架构设计与实践应用
AMD Ryzen处理器底层调试技术解析:SMUDebugTool的架构设计与实践应用 【免费下载链接】SMUDebugTool A dedicated tool to help write/read various parameters of Ryzen-based systems, such as manual overclock, SMU, PCI, CPUID, MSR and Power Table. 项目地…...
Manus开源框架:高效探索与开发灵巧手抓取技能
1. 项目概述与核心价值最近在机器人抓取领域,一个名为“Manus Open Claw Skill Hunter and Developer”的项目引起了我的注意。这个项目由Simplio Labs开源,它不是一个具体的硬件爪子,也不是一个单一的算法,而是一个专门用于发现、…...
WinFlexBison深度解析:Windows平台编译工具链的完整解决方案
WinFlexBison深度解析:Windows平台编译工具链的完整解决方案 【免费下载链接】winflexbison Main winflexbision repository 项目地址: https://gitcode.com/gh_mirrors/wi/winflexbison 在Windows平台上开发编译器、解释器或复杂文本解析器时,开…...
自制AVR ISP批量编程器:从ZIF插座到AVRDUDE一键烧录全攻略
1. 项目概述:为什么你需要一个批量编程器?如果你玩过Arduino或者自己做过一些基于AVR单片机的小项目,那么对“烧录程序”这个步骤一定不陌生。通常,我们是用一根USB线,或者一个USBasp、USBtinyISP这样的小编程器&#…...
