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

news2024/11/13 10:01:49

冒泡排序与其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 - 1
	for (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 - 1
	for (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 - 1
	for (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 - 1
	for (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函数 需要更改来解决。

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

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

相关文章

GD32F303RET6读取SGM58031电压值

1、SGM58031芯片详解 &#xff08;1&#xff09;SGM58031是一款低功耗&#xff0c;16位精度&#xff0c;delta-sigma (ΔΣ)模数转换器(ADC)。它从3V到5.5V供电。 &#xff08;2&#xff09;SGM58031包含一个片上参考和振荡器。它有一个I2C兼容接口&#xff0c;可以选择四个I2…

keepalived高可用集群

一、keepalived&#xff1a; 1.keepalive是lvs集群中的高可用架构&#xff0c;只是针对调度器的高可用&#xff0c;基于vrrp来实现调度器的主和备&#xff0c;也就是高可用的HA架构&#xff1b;设置一台主调度器和一台备调度器&#xff0c;在主调度器正常工作的时候&#xff0…

如何抓取和处理天气网站数据

目的 在进行气象研究时&#xff0c;获取准确的历史天气数据是至关重要的。本文将分享如何从天气网站收集数据并将其转化为表格形式&#xff0c;以便于后续分析。然而&#xff0c;在直接抓取数据时&#xff0c;可能会遇到API接口保护的问题。本文将详细解释解决这些问题的步骤&…

【人工智能】-- 受限玻尔兹曼机

个人主页&#xff1a;欢迎来到 Papicatch的博客 课设专栏 &#xff1a;学生成绩管理系统 专业知识专栏&#xff1a; 专业知识 文章目录 &#x1f349;引言 &#x1f349;受限玻尔兹曼机 &#x1f348;RBM的结构 &#x1f34d;RBM的架构图 &#x1f34d;RBM的经典实现 &…

“论软件维护方法及其应用”写作框架,软考高级论文,系统架构设计师论文

论文真题 软件维护是指在软件交付使用后&#xff0c;直至软件被淘汰的整个时间范围内&#xff0c;为了改正错误或满足 新的需求而修改软件的活动。在软件系统运行过程中&#xff0c;软件需要维护的原因是多种多样的&#xff0c; 根据维护的原因不同&#xff0c;可以将软件维护…

AI版Siri要明年见,研究表明ChatGPT暂无法取代程序员,Kimi推出浏览器插件

ChatGPT狂飙160天&#xff0c;世界已经不是之前的样子。 更多资源欢迎关注 根据彭博社记者马克古尔曼的最新消息&#xff0c;苹果公司今年不会推出全新的Apple Intelligence驱动的Siri&#xff0c;该公司计划在明年1月开始测试&#xff0c;并在iOS 18.4中才推出正式版本。 此前…

2.5 计算机网络

声明&#xff1a;文章参考的《系统架构设计师教程&#xff08;第二版&#xff09;》&#xff0c;如有侵权&#xff0c;本人将立即修改和删除。 利用通信线路将地理上分散的、具有独立功能的计算机系统和通信设备按不同的形式连接起来&#xff0c;并依靠网络软件以及通信协议实现…

[迫真保姆级教程]在Windows上编译可用的Tesseract OCR in C++ 并部署在Visual Studio与Qt6上

目录 前言 阅前提示 导言 使用基于vcpkg的&#xff0c;于msvc19编译器编译的Tessereact OCR动态库 使用vcpkg辅助我们的编译 正文 使用msys2环境下的&#xff0c;使用mingw64编译器编译的Tessereact OCR动态库 什么是msys2 安装前&#xff0c;我们也许。。。 [Option]…

入门PHP就来我这(高级)24 ~ Session判断用户登录

有胆量你就来跟着路老师卷起来&#xff01; -- 纯干货&#xff0c;技术知识分享 路老师给大家分享PHP语言的知识了&#xff0c;旨在想让大家入门PHP&#xff0c;并深入了解PHP语言。 上一篇我们介绍了Session管理部分的概念&#xff0c;本文通过session来改写一些用户登录&…

git批量删除本地包含某字符串的特定分支

git批量删除本地包含某字符串的特定分支 git branch -a | grep 分支中包含的字符串 | xargs git branch -D git删除本地分支_git查看删除本地分支-CSDN博客文章浏览阅读989次。git branch -d <分支名>可以通过: git branch 查看所有本地分支及其名字&#xff0c;然后删…

防火墙基础实验

首先交换机配置 [LSW7]undo info-center enable [LSW7]vlan batch 2 3 [LSW7]int g0/0/2 [LSW7-GigabitEthernet0/0/2]port link-type access [LSW7-GigabitEthernet0/0/2]port default vlan 2 [LSW7-GigabitEthernet0/0/2]int g0/0/3 [LSW7-GigabitEthernet0/0/3]port link-…

静态时序分析:Leaf Cell(叶单元)

相关阅读​​​​​​​静态时序分析https://blog.csdn.net/weixin_45791458/category_12567571.html 在DC中&#xff0c;leaf cell&#xff08;叶单元&#xff09;有时会出现在描述中&#xff0c;例如set_input_delay的-reference_pin选项的参数&#xff0c;就必须是一个端口或…

怎么将mkv视频格式转为mp4?这四种转换方法你肯定要试试!

怎么将mkv视频格式转为mp4&#xff1f;你是否曾被MKV格式的魅力深深吸引&#xff0c;仿佛踏入了一个充满奇幻色彩的多媒体秘境&#xff0c;那里&#xff0c;音频如溪流潺潺&#xff0c;视频似画卷铺展&#xff0c;字幕则如同夜空中最亮的星&#xff0c;三者交织成一场视听盛宴&…

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白名单…

多输入多输出 | Matlab实现Transformer多输入多输出预测

多输入多输出 | Matlab实现Transformer多输入多输出预测 目录 多输入多输出 | Matlab实现Transformer多输入多输出预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 多输入多输出 | Matlab实现Transformer多输入多输出预测&#xff08;完整源码和数据&#xff09; 1.da…

OS_同步与互斥

2024-07-04&#xff1a;操作系统同步与互斥学习笔记 第9节 同步与互斥 9.1 同步互斥的基本概念9.1.1 同步关系9.1.2 互斥关系9.1.3 临界资源9.1.4 临界区9.1.5 同步机制应遵循规则 9.2 软件同步机制9.2.1 单标志法9.2.2 双标志先检查法9.2.3 双标志后检查法9.2.4 peterson算法 …

windows安装Docker Desktop及国内镜像

简介 Docker 是一个开源的应用容器引擎&#xff0c;它让开发者可以打包他们的应用以及依赖包到一个可移植的容器中&#xff0c;然后发布到任何流行的 Linux 机器上&#xff0c;也可以实现虚拟化。通过Docker工具&#xff0c;简化了应用的部署、配置和管理过程&#xff0c;提高…

Python 核心编程

Python 核心编程 1. 数据类型1.1 整型 int1.2 浮点数 float1.3 布尔类型 bool1.4 字符串 str1.5 列表 list1.6 元组 tuple1.7 集合 set1.8 字典 dict 2. 逻辑结构、文件操作2.1 分支结构和三元表达2.2 循环和遍历2.3 目录和路径2.4 文件操作 3. 函数、类、异常处理3.1 函数3.2 …

int类型变量表示范围的计算原理

文章目录 1. 了解2. 为什么通常情况下int类型整数的取值范围是-2147483648 ~ 21474836473. int类型究竟占几个字节4. 推荐 1. 了解 通常情况下int类型变量占4个字节&#xff0c;1个字节有8位&#xff0c;每位都有0和1两种状态&#xff0c;所以int类型变量一共可以表示 2^32 种状…

p15 p16 c语言实现三子棋

具体的实现代码 game.c #include "game.h"void InitBoard(char board[ROW][COL], int row, int col) {int i 0;int j 0;for (i 0; i < row; i) {for (j 0; j < col; j) {board[i][j] ;}} }void DisplayBoard(char board[ROW][COL], int row, int col) …