c语言用冒泡排序模拟实现qsort排序

news2024/11/24 10:40:42

1、简单介绍冒泡排序

冒泡排序就是两两相邻元素进行比较,如果不满足顺序就进行交换。现有一组整数,将其用冒泡排序实现排序为升序。

假设有这样一组整数:9 8 7 6 5 

 由此可知,如果一个整型数组有num个元素,则需走num-1趟,若走在第i趟,则在第i趟内需要比较num-1-i次。

#include<stdio.h>
void bubble_sort(int arr[], int sz)
{
	int i = 0;
	//趟数
	for (i = 0; i < sz - 1; i++)
	{
		//一趟比较
		//两两相邻元素比较
		int j = 0;
		for (j = 0; j < sz - 1 - i; j++)
		{
			if (arr[j] > arr[j + 1])
			{
				arr[j] = arr[j + 1];
			}
		}
	}
}
int main()
{
	int arr[10] = { 9,8,7,6,5,4,3,2,1,0 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	bubble_sort(arr, sz);
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

2、介绍qsort函数

void qsort(void* base, //指向了需要排序的数组的第一个元素

                 size_t num, //排序的元素个数

                size_t size,//一个元素的大小,单位是字节

                int (*cmp)(const void*, const void*)//函数指针类型 ,此函数指针指向的函数能够比较base指向数组中的两个元素

                );

int cmp (const void* p1, const void* p2);

该函数通过返回值来定义元素的顺序

返回值意义
>0p1指向的元素 在p2指向的元素之前
0p1指向的元素等效于p2指向的元素
<0p1指向的元素在p2指向的元素之后

void* 的指针是没有具体类型的指针,这类指针可以接受任意类型的地址,但是这类指针不能直接解引用操作,也不能直接进行指针运算。

qsort函数的特点:

                1、是快速排序的方法

                2、适用于任意类型数据的排序

3、用冒泡排序模拟实现qsort排序

        将冒泡排序封装成函数,如上buttle_sort(),则此函数需传递同类型的参数且参数个数相等:void buttle_sort(void* base,rsize_t num,size_t size,int(*cmp)(const void*,const void*)),且由于传递的数据类型不确定,则比较的方法和交换数据的方法有所不同,故可以使用函数来封装比较和交换的方法,由于冒泡排序函数buttle_sort传递的是首元素的地址,

若想比较并交换两个元素就需要元素的地址,故比较函数和交换函数传递的参数都为元素地址,由于传递参数的类型不确定,那么元素的大小也无法确定,int类型的指针通过首元素地址加其所对应下标即为其地址,而void*类型指针无法直接进行指针运算,需将其类型强制转换,冒泡排序函数buttle_sort传递size为元素的字节个数,char为最小字节的类型,可以用来比较任意类型的数据,故将(void*)base强制转化为(char*)base,故void*类型的指针可通过(char*)base + j * size,(char*)base+(j+1)*size来解引用比较相邻元素的大小,故比较函数为cmp((char*)base + j * size,(char*)base+(j+1)*size),交换函数为swp((char*)base + j * size, (char*)base + (j + 1) * size,size),就有了如下函数的代码

//交换
void swp(char* butt1, char* butt2,int size)
{
	int i = 0;
	for(i; i < size; i++)
	{
		char temp = *butt1;
		*butt1 = *butt2;
		*butt2 = temp;
		butt1++;
		butt2++;
	}
}
//冒泡排序所有类型数据
void buttle_sort(void* base,rsize_t num,size_t size,int(*cmp)(const void*,const void*))
{
	int i = 0;
	//趟数,需要n-1趟
	for (i; i < num - 1; i++)
	{
		int j = 0;
		//每趟比较次数
		for (j; j < num - 1 - i; j++)
		{
			//比较,若按升序排列,cmp返回值需>0
			if (cmp((char*)base + j * size,(char*)base+(j+1)*size)>0)
			{
				//交换
				swp((char*)base + j * size, (char*)base + (j + 1) * size,size);
			}
		}
	}
}

比较函数的具体实现因数据类型不同而不同,故比较函数由操。作方即调用函数的一方来书写实现过程。

测试1

#include<stdio.h>

//整型比较
int cmp_int(const void* p1 ,const void* p2 )
{
    return (*(int*)p1 - *(int*)p2);
}

void test1()//qsort测试整形数据
{
    int a[10] = { 2,1,3,0,5,7,4,9,6,8 };
    int num = sizeof(a) / sizeof(a[0]);
    buttle_sort(a, num, sizeof(a[0]), cmp_int);
    int i = 0;
    for (i; i < num; i++)
    {
        printf("%d \n",a[i]);
    }
}

int main()
{
    test1();
    return 0;
}

测试结果:

测试2

#include<stdio.h>
#include<string.h>

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

//结构体通过名字比较
int cmp_struct_by_name(const void* p1, const void* p2)
{
    return strcmp((struct Stu*)p1->name, (struct Stu*)p2)->name;
}


void test2()//qsort测试结构体数据
{
    struct Stu stu[3] = { {"zhangsan",20},{"lisi",50},{"wangwu",15} };
    int num = sizeof(stu) / sizeof(stu[0]);
    buttle_sort(stu, num, sizeof(stu[0]), cmp_struct_by_name);
    int i = 0;
    for (i; i < num; i++)
    {
        printf("%s %d\n", stu[i].name, stu[i]age);
    }
}

int main()
{
    test2();
    return 0;
}

测试结果:

 

测试3

#include<stdio.h>

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

//结构体通过年龄比较
int cmp_struct_by_age(const void* p1, const void* p2)
{
    return  ((struct Stu*)p1)->age - ((struct Stu*)p2)->age;
}

void test3()//qsort测试结构体数据
{
    struct Stu stu[3] = { {"zhangsan",20},{"lisi",50},{"wangwu",15} };
    int num = sizeof(stu) / sizeof(stu[0]);
    buttle_sort(stu, num, sizeof(stu[0]), cmp_struct_by_age);
    int i = 0;
    for (i; i < num; i++)
    {
        printf("%s %d\n",stu[i].name,stu[i]age);
    }
}
int main()
{
    test3();
    return 0;
}

测试结果:

 

 

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

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

相关文章

第一次作业 运维高级 MySQL备份与还原

1.创建student和score表 CREATE TABLE student ( id INT(10) NOT NULL UNIQUE PRIMARY KEY , name VARCHAR(20) NOT NULL , sex VARCHAR(4) , birth YEAR, department VARCHAR(20) , address VARCHAR(50) );CREATE TABLE score ( id INT(10) NOT NULL UNIQUE PRIMARY KEY AUTO…

交叉编译----宿主机x86 ubuntu 64位-目标机ARMv8 aarch64

1.交叉编译是什么&#xff0c;为什么要交叉编译 编译&#xff1a;在一个平台上生成在该平台上的可执行代码交叉编译&#xff1a;在一个平台上生成在另一个平台上的可执行代码交叉编译的例子&#xff1a;如51单片机的可执行代码&#xff08;hex文件&#xff09;是在集成环境kei…

区间预测 | MATLAB实现QRGRU门控循环单元分位数回归多输入单输出区间预测

区间预测 | MATLAB实现QRGRU门控循环单元分位数回归时间序列区间预测 目录 区间预测 | MATLAB实现QRGRU门控循环单元分位数回归时间序列区间预测效果一览基本介绍模型描述程序设计参考资料 效果一览 基本介绍 MATLAB实现QRGRU门控循环单元分位数回归分位数回归多输入单输出区间…

【Docker】安全及日志管理

目录 一、Docker 安全及日志管理1.1 Docker 容器与虚拟机的区别1. 隔离与共享2. 性能与损耗 1.2Docker 存在的安全问题1.Docker 自身漏洞2.Docker 源码问题 1.3 Docker 架构缺陷与安全机制1. 容器之间的局域网攻击2. DDoS 攻击耗尽资源3. 有漏洞的系统调用4. 共享root用户权限 …

Python in VS Code 2023年7月发布|Mypy 扩展预览版与调试扩展、Pylance 本地化及其他

排版&#xff1a;Alan Wang 我们很高兴地宣布 Visual Studio Code 的 Python 和 Jupyter 扩展将于 2023 年 7 月发布&#xff01; 此版本包括以下更新&#xff1a; Mypy 扩展预览版预览版中的调试扩展Pylance 本地化使用 Pylance 的第三方库的索引持久性即将弃用 Python 3.7 支…

新功能 – Cloud WAN:托管 WAN 服务

我很高兴地宣布&#xff0c;我们推出了 Amazon Cloud WAN&#xff0c;这是一项新的网络服务&#xff0c;它可以轻松构建和运营连接您的数据中心和分支机构以及多个 Amazon 区域中的多个 VPC 的广域网&#xff08;WAN&#xff09;。 亚马逊云科技开发者社区为开发者们提供全球的…

win10 双系统 安装 Ubuntu20.04 记录

写这篇博客的原因 我今天晚上想重装ubuntu&#xff0c;结果不小心用genius 把属于win10的分区也给删除&#xff0c;只保留C盘和D盘。重装win10之后&#xff0c;我以为D盘还会有数据在&#xff0c;结果啥没了&#xff0c;甚至我的毕业照都没了。所以还是要准备一块移动硬盘&…

redis启动失败,oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo

在redis文件夹下&#xff0c;启动redis正常。 但是加入到system后启动redis失败。 一直处于starting状态。 对比正常redis服务的配置之后&#xff0c;把redis.conf里的守护进程关掉就可以了&#xff08;但是没用system管理之前&#xff0c;直接./redis.server启动是可以的&…

【Lua学习笔记】Lua进阶——函数和闭包

文章目录 函数函数嵌套闭包Closures可变函数函数重载 函数 函数嵌套 function A()print("这里是函数A")return function ()print("返回函数不要起名")end end B A() B()输出&#xff1a; 这里是函数A 返回函数不要起名使用函数嵌套的用法&#xff0c;我…

springboot 之以enable开头的注解

Spring​ 有很多 Enable 开头的注解&#xff0c;平时在使用的时候也没有注意过为什么会有这些注解 Enable 注解 首先我们先看一下有哪些常用的 Enable 开头的注解&#xff0c;以及都是干什么用的。 EnableRetry​&#xff1a;开启Spring 的重试功能&#xff1b; EnableSch…

Guitar Pro8吉他谱制作软件好不好用?

吉他谱是学习和演奏吉他的重要工具之一&#xff0c;对于吉他爱好者而言&#xff0c;掌握一款优秀的吉他谱制作软件是必不可少的。随着科技的进步&#xff0c;现在有许多吉他谱制作软件可供选择。下面我们就来看吉他谱制作软件哪个好&#xff0c;以及怎么制作吉他谱子吧&#xf…

Vue前端渲染blob二进制对象图片的方法

近期做开发&#xff0c;联调接口。接口返回的是一张图片&#xff0c;是对二进制图片处理并渲染&#xff0c;特此记录一下。 本文章是转载文章&#xff0c;原文章&#xff1a;Vue前端处理blob二进制对象图片的方法 接口response是下图 显然&#xff0c;获取到的是一堆乱码&…

HEVC网络适配层介绍

h265 的分层结构 分层结构的目的 ○ 网络类型多种多样&#xff0c;不同的网络环境具有不同的特性&#xff0c;压缩视频在其中进行传输必然会受到影响&#xff1b;比如不同网络的 MTU 有所不同&#xff1b; ○ 不同的应用场景对视频有不同的需求&#xff0c;视频业务会喜用不…

Llama 2 来袭 - 在 Hugging Face 上玩转它

&#x1f917; 宝子们可以戳 阅读原文 查看文中所有的外部链接哟&#xff01; 引言 今天&#xff0c;Meta 发布了 Llama 2&#xff0c;其包含了一系列最先进的开放大语言模型&#xff0c;我们很高兴能够将其全面集成入 Hugging Face&#xff0c;并全力支持其发布。Llama 2 的社…

Sentinel Dashboard集成Nacos

1.前言 当项目上Sentinel Dashboard做流量监控的时候&#xff0c;我们可以通过Sentinel控制台修改限流配置&#xff0c;但当我们使用Nacos作为配置中心动态配置流控规则的时候&#xff0c;问题就来了。 首先我们要明白&#xff0c;Sentinel Dashboard的配置是从机器的内存中加…

go学习 3、基础数据类型

3、基础数据类型 基础数据类型&#xff1a;数字、字符串、布尔型复合类型&#xff1a;数组、结构体引用类型&#xff1a;指针、切片、字典、函数、通道接口类型 3.1 整型 有符号、无符号 int8/int16/int32/int64 uint8/uint16/uint32/units 64 Unicode字符rune类型是和int32…

R语言无法调用stats.dll的问题解决方案[补充]

写在前面 在去年10月份&#xff0c;出过一起关于R语言无法调用stats.dll的问题解决方案,今天&#xff08;你看到后是昨天&#xff09;不知道为什么&#xff0c;安装包&#xff0c;一直安装不了&#xff0c;真的是炸裂了。后面再次把R与Rstuido升级。说实话&#xff0c;我是真不…

整套停车位地磁检测方案出售,主控使用stm32驱动nb-iot模块bc95数据上传远程云服务器。

地磁车辆检测器&#xff0c;是车辆本身含有的铁磁物质会对车辆存在区域的地磁信号产生影响&#xff0c;使车辆存在区域的地球磁力线发生弯曲。当车辆经过传感器附近&#xff0c;传感器能够灵敏感知到信号的变化&#xff0c;经信号分析就可以得到检测目标的相关信息。 朋友创业…

安装github中的存储库作为Python包

第一步&#xff0c;安装git 安装教程&#xff1a;https://zhuanlan.zhihu.com/p/114068278 第二步&#xff0c;在github上复制该库的链接 第三步&#xff0c;使用命令行一键下载并安装包 pip install "githttps://github.com/openai/CLIP.git"如果当pip install…

笔记本充满电后,充电器可以长期不拔,会议安全隐患吗?

笔记本充满电后&#xff0c;一直插着不拔 1.建议人在身边可以暂时不拔&#xff0c;偶尔还是要使用电池当笔记本电池充满之后&#xff0c;电脑会自动使用电源供电&#xff0c;不会使用电池供电 2.笔记本电池都带有电池保护机制&#xff0c;在电池充满电后会自动停止充电 3.现在…