【数据结构】第十九弹---C语言实现冒泡排序算法

 ✨个人主页: 熬夜学编程的小林

💗系列专栏: 【C语言详解】 【数据结构详解】【C++详解】

目录

1、冒泡排序基本思想

2、代码的初步实现

3、代码的优化

4、代码的测试

5、时空复杂度分析

6、模拟实现qsort

6.1、冒泡排序函数

6.2、交换数据函数

6.3、比较函数

总结


1、冒泡排序基本思想

冒泡排序法:(Bubble sort)是一种基础的交换排序。对数组进行遍历,每次对相邻两个进行比较大小,若大的数值在前面则交换位置(升序),完成一趟遍历后数组中最大的数值到了数组的末尾位置,再对前面n-1个数值进行相同的遍历,完成n-1次遍历则排序完成。

1. 第一趟对0~n-1遍历,依次对比前后的大小,若是不满足前小后大就交换,此时最大的数就被挪到了最后一个位置。

2. 对0~n-2遍历,继续比较前后大小,此时前n-2个数中最大的数就到了倒数第二个位置。

3. 重复上述动作继续遍历,每一次都将最大的数向后挤,直到遍历完毕排序成功。

2、代码的初步实现

对int 类型的数进行升序排序。

//交换函数
void Swap(int* p1, int* p2)
{
	int tmp = *p1;
	*p1 = *p2;
	*p2 = tmp;
}
void BubbleSort(int* a, int n)
{
	for (int i = 0; i < n - 1; i++)//遍历n-1次
	{
		for (int j = 0; j < n - 1 - i; j++)//相邻两个数进行比较
		{
			if (a[j] > a[j + 1])//前面的值大于后面的值则交换
			{
				Swap(&a[j], &a[j + 1]);
			}
		}
	}
}

3、代码的优化

如果一次遍历,没有数据进行交换,则证明数组已经排好了顺序,不需要继续遍历,则引入exchange变量标志记录第一次遍历是否有数据交换。

void BubbleSort(int* a, int n)
{
	for (int i = 0; i < n - 1; i++)
	{
		bool exchange = false;//默认false,值没变则没有交换
		for (int j = 0; j < n - 1 - i; j++)//遍历n-1次
		{
			if (a[j] > a[j + 1])//相邻两个数进行比较
			{
				Swap(&a[j], &a[j + 1]);//前面的值大于后面的值则交换
				exchange = true;
			}
		}
		if (exchange == false)//值没变则退出内循环
			break;
	}
}

4、代码的测试

测试代码:

//测试冒泡排序
int main()
{
	int a[] = { 9,8,7,6,5,4,3,2,1,0 };//给一组数据
	int sz = sizeof(a) / sizeof(a[0]);//计算数组元素个数
	printf("排序前:\n");
	ArrayPrint(a, sz);
	BubbleSort(a, sz);
	printf("排序后:\n");
	ArrayPrint(a, sz);
	return 0;
}

测试结果: 

5、时空复杂度分析

时间复杂度:

最坏情况:

当我们需要排升序的时候,原数组为降序,则为最坏情况。此时每次交换操作需要比较的次数从 n-1 次减少到 1 次,总共的比较次数是 (n-1) + (n-2) + … + 1 = n(n-1)/2,这是一个二次函数,因此时间复杂度为 O(n^2)。

最好情况:

当我们需要排升序时,原数组也是升序,我们只需要循环n次则可以判断结束,此时时间复杂度为O(N)。

由于时间复杂度取决于最坏情况,因此冒泡排序的时间复杂度为O(N^2)。

空间复杂度:

冒泡排序是一种原地排序算法,除了输入数组外,它只需要有限的几个变量(比如,交换标记和循环计数器)。因此,它的空间复杂度为常数空间O(1)。

6、模拟实现qsort

C语言中库函数 qsort是通过函数指针cmp传入数据类型的比较方式,实现对各种数据类型都能进行排序的功能。

我们将模仿qsort函数使用冒泡排序算法实现对各种数据类型都能进行排序的函数,并且使用const关键字严格限制参的属性,达到很高的健壮性要求。

6.1、冒泡排序函数

库函数qsort()函数接口:

void qsort (void* base, size_t num, size_t size,
            int (*com)(const void*,const void*));

模拟实现的函数接口:

void bubble_sort(void* base, //待排序数组首元素地址
                 size_t num, //待排序数组元素个数
                 size_t size,//待排序数组元素类型大小,单位为字节
                 int (*com)(const void*,const void*)//函数指针 如何进行比较函数
);

6.2、交换数据函数

void swap(char* buf1, char* buf2, size_t size);

思想:

以1个字节为单位对两个指针指向的内容进行交换交换size次即可。

参数:

buf1:被交换的数据的地址。
buf2:被交换的数据的地址。
size:被交换数据类型的字节大小。

void swap(char* buf1, char* buf2, size_t size)
{
	assert(buf1 && buf2);//断言,指针不为空才能交换
	size_t i = 0;
	for (i = 0; i < size; i++)
	{
		char tmp = *buf1;
		*buf1 = *buf2;
		*buf2 = tmp;
		buf1++;
		buf2++;
	}
}

6.3、比较函数

int cmp(const void* e1, const void* e2);

 void*是一个空类型的指针,可以存放任意类型的指针。

此处就用到了void*,void*为空指针,不能直接使用但是可以强转为其他的任何类型,那么此处我们应该强转成什么类型呢?直接强转成int*?很显然,如果强转为int*,那么char*,short*就不好进行转化了,因此此处转化为char*,如果要用到其他的类型,我们通过+数据类型大小就可以得到因此我们需要将指针转换成char*,依次按照字节进行交换。

返回值:

大于0,e1大;等于0,一样大;小于0,e2大。

参数:

e1:被比较的数据的地址,由void*指针接收,由const限制不能改变指针指向,但可以改变指针指向的内容。
e1:被比较的数据的地址,由void*指针接收,由const限制不能改变指针指向,但可以改变指针指向的内容。

函数体:

用户自定义实现数值的比较规则。

传参:

1. 被比较数值的地址由void*指针接收。

2. 数值在数组中第 i 个位置:将void*转换成char指针,(char*)base + i*size 。

一些规则的演示:

//int类型数据比较(升序)
int cmp(const void* e1, const void* e2)
{
    return *(int*)e1 - *(int*)e2;
}

//int类型数据比较(降序)
int cmp(const void* e1, const void* e2)
{
    return *(int*)e2 - *(int*)e1;	//降序就是把e1,e2的位置交换一下
}

//字符串比较(按字母升序)
#include <string.h>
int cmp(const void* e1, const void* e2)
{
    return strcmp((char*)e1, (char*)e2);	//字符串比较函数,与前面的比较规则一致
}

冒泡排序法的实现

#include <assert.h>		//引入头文件<assert.h>,使用assert函数断言

//交换数据
void swap(char* buf1, char* buf2, size_t size)
{
	assert(buf1 && buf2);//断言,指针不为空才能交换
	size_t i = 0;
	for (i = 0; i < size; i++)
	{
		char tmp = *buf1;
		*buf1 = *buf2;
		*buf2 = tmp;
		buf1++;
		buf2++;
	}
}

//冒泡排序法
void bubble_sort(void* base,size_t num,size_t size,int (*cmp)(const void* e1,const void* e2))
{
	size_t i = 0;
	for (i = 0; i < num - 1; i++)
	{
		size_t j = 0;
		for (j = 0; j < num - 1 - i; j++)
		{
			//if (arr[j] > arr[j + 1])
			//(char*)base+j*size,(char*)base+(j+1)*size
			if(cmp((char*)base + j * size, (char*)base + (j + 1) * size)>0)
			{
				swap((char*)base + j * size, (char*)base + (j + 1) * size,size);
			}
		}
	}
}

1.整型数组降序排序的演示

//整型降序比较函数
int cmp_int(void* e1, void* e2)
{
	return *((int*)e2) - *((int*)e1);
}

void test1()
{
	int arr[] = { 0,1,2,3,4,5,6,7,8,9 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	print_arr(arr, sz);//打印数组元素
	bubble_sort(arr, sz, sizeof(arr[0]), cmp_int);
	print_arr(arr, sz);//打印数组元素
}

测试结果: 

2.结构体演示 

struct Stu
{
	char name[20];
	int age;
};

int cmp_stu_by_age(const void* e1,const void* e2)
{
	return ((struct Stu*)e1)->age - ((struct Stu*)e2)->age;
}

void test2()
{
	struct Stu arr[] = { {"zhangsan",18},{"lisi",32},{"wangwu",20} };
	int sz = sizeof(arr) / sizeof(arr[0]);
	bubble_sort(arr, sz, sizeof(arr[0]), cmp_stu_by_age);
}

测试结果: 

总结


本篇博客就结束啦,谢谢大家的观看,如果公主少年们有好的建议可以留言喔,谢谢大家啦!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【PyTorch】【机器学习】图片张量、通道分解合成和裁剪

一、导入所需库 from PIL import Image import torch import numpy as np import matplotlib.pyplot as plt二、读取图片 pic np.array(Image.open(venice-boat.jpg))上述代码解释&#xff1a;先用Image.open()方法读取jpg格式图片&#xff0c;再用np.array()方法将图片转成…

STM32单片机-BKP和RTC

STM32单片机-BKP和RTC 一、Unix时间戳1.1 时间戳转换 二、BKP(备份寄存器)三、RTC(实时时钟)3.1 RTC工作原理 四、代码部分4.1 BKP备份寄存器4.2 RTC实时时钟 一、Unix时间戳 Unix时间戳定义为从伦敦时间的1970年1月1日0时0分0秒开始所经过的秒数&#xff0c;不考虑闰秒时间戳…

Django集成OpenAI

Django集成OpenAI 通过前面 django 框架的基本开发知识&#xff0c;我们现在可以开始在 django 上做稍微深一点当然应用开发了。 这一章开始编写怎么集成调用 openai &#xff0c;设置环境以及 openai 的基础知识。 大家都知道 ai 的多模态逐渐扩大&#xff0c;各种应用层出…

【LeetCode:2663. 字典序最小的美丽字符串 + 贪心】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

性能工具之 JMeter 常用组件介绍(五)

文章目录 一、Jmeter中参数取值1、Test Plan中添加变量2、User Defined Variables 二、Jmeter中CSV Data Set Config三、Timer:定时器4、Gaussian Random Timer 高斯随机定时器5、JSR223 Timer JSR223定时器6、Poisson Random Timer 泊松随机定时器7、Synchronizing Timer 同步…

复分析——第4章——Fourier变换(E.M. Stein R. Shakarchi)

第4章 Fouier变换 Raymond Edward Alan Christopher Paley, Fellow of Trinity College, Cambridge, and International Research Fellow at the Massachusetts Institute of Technology and at Harvard University, was killed by an avalanche on April 7, 1933, whi…

记某模版菠菜管理后台登录思路

1.前言 由于小程序的便捷性&#xff0c;越来越多的应用迁移到了了小程序上&#xff0c;由此伴随着小程序上线前的日常渗透测试工作也开始增加。但小程序的测试中经常会遇到数据包被加密了&#xff0c;导致无法进行改包测试。和测试网页数据包加密一样&#xff0c;就需要找到小…

Stable Diffusion 3 文本生成图像 在线体验 原理分析

前言 本文分享使用Stable Diffusion 3实现文本生成图像&#xff0c;可以通过在线网页中免费使用的&#xff0c;也有API等方式访问。 同时结合论文和开源代码进行分析&#xff0c;理解其原理。 Stable Diffusion 3是Stability AI开发的最新、最先进的文本生成图像模型&#x…

Linux中部署MySQL环境方法(仓库安装)

1.进入MySQL官网 2.进入MySQL社区版下载 3.使用yum方式下载MySQL 4.使找到对应系统的对应包的链接 复制 5.linux命令行中使用命令通过对应链接下载该软件包 rpm -i https://repo.mysql.com//mysql80-community-release-el9-1.noarch.rpm 警告&#xff1a;/var/tmp/rpm-tmp.so…

45、基于深度学习的螃蟹性别分类(matlab)

1、基于深度学习的螃蟹性别分类原理及流程 基于深度学习的螃蟹性别分类原理是利用深度学习模型对螃蟹的图像进行训练和识别&#xff0c;从而实现对螃蟹性别的自动分类。整个流程可以分为数据准备、模型构建、模型训练和性别分类四个步骤。 数据准备&#xff1a; 首先需要收集包…

分享一个 Fail2ban 过滤规则

今天明月给大家分享个 Fail2ban 的过滤&#xff08;Filter&#xff09;规则&#xff0c;有关 Fail2ban 的文章大家可以参考【服务器全面使用 Fail2Ban 初见成效】和【使用 Fail2ban 禁止垃圾采集爬虫&#xff0c;保护 Nginx 服务器】等文了解&#xff0c;总之 Fail2ban 是 Linu…

如何跳出认知偏差,个人认知能力升级

一、教程描述 什么是认知力&#xff1f;认知力&#xff08;cognitive ability&#xff09;&#xff0c;实际上就是指一个人的认知能力&#xff0c;是指人的大脑加工、储存和提取信息的能力&#xff0c;或者主观对非主观的事物的反映能力&#xff0c;如果变成大白话&#xff0c…

力扣SQL 即时食物配送 II min函数 嵌套查询

Problem: 1174. 即时食物配送 II &#x1f468;‍&#x1f3eb; 参考题解 Code -- 计算立即配送的订单百分比 select round (-- 计算订单日期与客户偏好配送日期相同的订单数量sum(case when order_date customer_pref_delivery_date then 1 else 0 end) * 100 /-- 计算总订…

媒体邀约中媒体采访应该如何做?

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 媒体宣传加速季&#xff0c;100万补贴享不停&#xff0c;一手媒体资源&#xff0c;全国100城线下落地执行。详情请联系胡老师。 在媒体邀约中&#xff0c;媒体采访应该遵循以下几个步骤和…

[C#]使用深度学习算法opencvsharp部署RecRecNet广角图像畸变矫正校正摄像广角镜头畸变图像

【论文地址】 https://arxiv.org/abs/2301.01661 【训练源码】 https://github.com/KangLiao929/RecRecNet 【参考源码】 https://github.com/hpc203/recrecnet-opencv-dnn 【算法介绍】 广角镜头在VR技术中显示出诱人的应用&#xff0c;但它会在捕获的图像中引入严重的径…

如何下载和安装SQLynx数据库管理工具? (MySQL作为测试数据库)

目录 1. 官网下载 2. 安装软件 3. 启动SQLynx软件 4. 开始使用 5. 执行第一条SQL语句 6. 总结 SQLynx是一款先进的Web SQL集成开发环境&#xff08;IDE&#xff09;&#xff0c;专为数据库管理、查询和数据分析设计。作为一个基于浏览器的工具&#xff08;同时也支持桌面…

《计算机英语》Unit2 Operating System and Computer Architecture 操作系统和计算机构造

SectionA Operating System操作系统 不同操作系统 批处理操作系统(Batch Processing Operating System) 分时操作系统(Time Sharing Operating System) 实时操作系统(Real Time Operating System) 个人操作系统(Personal Operating System) 网络操作系统(NOS, Network Operati…

Android设计模式系列--模板方法模式

认识到模板方法的这种思想&#xff0c;父类可以让未知的子类去做它本身可能完成的不好或者根本完成不了的事情&#xff0c;对框架学习大有帮助。 本文以View中的draw方法为例&#xff0c;展开分析。 模板方法&#xff0c;TemplateMethod&#xff0c;光是学习这个模式&#xf…

SwiftUI 6.0(iOS 18)ScrollView 全新的滚动位置(ScrollPosition)揭秘

概览 在只有方寸之间大小的手持设备上要想体面的向用户展示海量信息&#xff0c;滚动视图&#xff08;ScrollView&#xff09;无疑是绝佳的“东牀之选”。 在 SwiftUI 历史的长河中&#xff0c;总觉得苹果对于 ScrollView 视图功能的升级是在“挤牙膏”。这不&#xff0c;在本…

“一站式企业服务平台”的功能架构

为提升区域营商环境&#xff0c;为促进区域经济发展&#xff0c;实现资源高效配置&#xff0c;全国各区域政府及产业园区都越来越重视如何创新企业服务机制、提升企业服务水平&#xff0c;来保障区域内的企业稳定及帮扶企业高质量的发展。随着近年来大数据、人工智能等新一代信…