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

冒泡排序与其C语言通用连续类型排序代码

冒泡排序与其C语言通用连续类型排序代码

  • 冒泡排序
    • 冒泡排序为交换排序的一种:
    • 动图展示:
    • 冒泡排序的特性总结:
    • 冒泡排序排整型数据参考代码(VS2022C语言环境):
  • 冒泡排序C语言通用连续类型排序代码
    • 对比较的方式更改:
    • 对交换的方式更改:
    • 结果验证:
      • 内置类型:
      • 自定义类型:
    • 注意:

冒泡排序

冒泡排序为交换排序的一种:

  1. 基本思想:所谓交换,就是根据序列中两个记录键值的比较结果来对换这两个记录在序列中的位置。
  2. 交换排序的特点是:将键值较大的记录向序列的尾部移动,键值较小的记录向序列的前部移动。

而冒泡排序升序时每遍历一次会将未排好的集合中大的值移动到后面(或小的移到前面),直到排好序。

动图展示:

在这里插入图片描述

冒泡排序的特性总结:

  1. 冒泡排序是一种非常容易理解的排序
  2. 时间复杂度:O(N ^ 2)
  3. 空间复杂度:O(1)
  4. 稳定性:稳定

冒泡排序排整型数据参考代码(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函数 需要更改来解决。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • SpringBoot新手快速入门系列教程五:基于JPA的一个Mysql简单读写例子
  • [C++] 模拟实现list(二)
  • STM32杂交版(HAL库、音乐盒、闹钟、点阵屏、温湿度)
  • 论文学习_An Empirical Study of Deep Learning Models for Vulnerability Detection
  • 利用 Plotly.js 创建交互式条形图
  • 【js面试题】深入理解浏览器对象模型(BOM)
  • HiFi音频解码器:音质提升的秘密武器
  • ios swift5 蓝牙广播出数据
  • 蚁剑编码器编写——php木马免杀
  • DID差分模型案例集(传统DID、队列DID、渐近DID、空间DID、PSM-DID)
  • 使用 FFmpeg 处理视频:简介、常用命令及在 C++ 中调用 FFmpeg
  • jmeter-beanshell学习3-beanshell获取请求报文和响应报文
  • dify/api/models/workflow.py文件中的数据表
  • 防火墙安全策略练习
  • uiautomation: debug记录
  • [NodeJS] 关于Buffer
  • 《网管员必读——网络组建》(第2版)电子课件下载
  • 【EOS】Cleos基础
  • 【许晓笛】 EOS 智能合约案例解析(3)
  • CentOS7简单部署NFS
  • IOS评论框不贴底(ios12新bug)
  • JavaScript-Array类型
  • mysql_config not found
  • Objective-C 中关联引用的概念
  • oldjun 检测网站的经验
  • PHP 使用 Swoole - TaskWorker 实现异步操作 Mysql
  • Vue 动态创建 component
  • vue中实现单选
  • vue自定义指令实现v-tap插件
  • Webpack 4 学习01(基础配置)
  • XML已死 ?
  • Zepto.js源码学习之二
  • 彻底搞懂浏览器Event-loop
  • 官方新出的 Kotlin 扩展库 KTX,到底帮你干了什么?
  • 手写一个CommonJS打包工具(一)
  • 网络应用优化——时延与带宽
  • 用element的upload组件实现多图片上传和压缩
  • 7行Python代码的人脸识别
  • ​一些不规范的GTID使用场景
  • ## 基础知识
  • #微信小程序(布局、渲染层基础知识)
  • (libusb) usb口自动刷新
  • (附源码)springboot建达集团公司平台 毕业设计 141538
  • (每日持续更新)jdk api之StringBufferInputStream基础、应用、实战
  • (免费领源码)python#django#mysql校园校园宿舍管理系统84831-计算机毕业设计项目选题推荐
  • (三)elasticsearch 源码之启动流程分析
  • (四)事件系统
  • (学习日记)2024.04.04:UCOSIII第三十二节:计数信号量实验
  • (转)我也是一只IT小小鸟
  • *算法训练(leetcode)第四十五天 | 101. 孤岛的总面积、102. 沉没孤岛、103. 水流问题、104. 建造最大岛屿
  • .bat批处理(一):@echo off
  • .Family_物联网
  • .NET CORE使用Redis分布式锁续命(续期)问题
  • .NetCore部署微服务(二)
  • .pub是什么文件_Rust 模块和文件 - 「译」