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

c---冒泡排序模拟qsort

一、冒泡排序

二、冒泡排序优化排各种类型数据

文章目录

  • 一、冒泡排序
    • 二、冒泡排序优化排各种类型数据


冒泡排序

冒泡排序原理:两两相邻元素进行比较
在这里插入图片描述
在这里插入图片描述

初级版

void bulle_sort(int* a, int sz)
{
	int i = 0;
	for (int i = 0; i < sz-1; i++)
	{
		int j = 0; 
		for (j = 0; j < sz - 1 - i; j++)
		{
			if (a[j] > a[j+1])
			{
				int tmp = a[j];
				a[j] = a[j + 1];
				a[j + 1] = tmp;

			}
		}
	}
}

这是冒泡排序初级版,不管其原内容是否有序都会进行比较,如果原内容原本就是有序的,再每个都进行比较效率就会低下,那么这时候可以改进一下,想一个标记变量来记录是否有序,如int
falg = 0; 如果无序的情况下falg会变为1,有序的情况下falg保持0不变,如果一趟下来falg 为0
不变,那么就是有序的就不用再比较后面趟数了,这样使其在有序的情况下时间复杂度为O(n),大大提高了效率

改进版

void bulle_sort(int* a, int sz)
{
	int i = 0;
	int falg = 0;
	for (int i = 0; i < sz-1; i++)
	{
		int j = 0; 
		for (j = 0; j < sz - 1 - i; j++)
		{
			if (a[j] > a[j+1])
			{
				int tmp = a[j];
				a[j] = a[j + 1];
				a[j + 1] = tmp;
				falg = 1;
			}
		}

		if (falg == 0)
		{
			break;
		}
	}
}

冒泡排序优化排各种类型数据
上面冒泡排序可以发现只能够排序整形
在这里插入图片描述
那要是我们想利用冒泡来排其他不同类型应该如何实现呢?这里就引入c语言里的一个库函数qsort(),在cplusplus上搜索qosrt

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

可以发现这是一个排序函数,且qsort函数有四个参数,void * base目标数组,待排序的起始地址,size_t num待排序数组大小,size_t表示无符号类型,由于数组大小不可能为负数,因此设置为size_t更为合适,size_t size,数组中每个元素是多少字节,其实就是每个元素是什么类型
在这里插入图片描述

int (*compar)(const void*,const void*)

这是一个函数指针,是比较函数的函数指针,而comper实现的是比较功能,
在这里插入图片描述
比较函数在这里插入图片描述

由于比较类型不知道是什么类型的,因此用void*,这里这个设计十分合理,void*,void*存的是要比较两个元素的地址,是因为设计者在设计时不知道我们要比较什么类型的,因为void*指针可以接收任意类型变量的地址。comper函数返回类型为in类型,第一个比第二个于返回1,相等返回0,小于返回-1


qsort函数运用

int comper(const void* s1, const void* s2)
{
	return *((int*)s1) - *((int*)s2);//由于我们自己使用时知道了是什么类型,因此强转为该类型就可,
	//然后再对其解引用就可以相互进行比较了
}
int main()
{
	int arr[] = { 9,8,7,6,5,4,3,2,1 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	//bulle_sort(arr, sz);
	qsort(arr, sz, sizeof(arr[0]), comper);
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
	return 0;
}

在这里插入图片描述

可以发现出了警告是qsort未定义,这是因为没有包含它所需的头文件

在这里插入图片描述

可以往下翻找到它该用什么头文件
以qsort排序结构体

#include<string.h>
typedef struct Stu
{
	char name[20];
	int age;
}Stu;
int comper_stu_by_name(const void* s1, const void* s2)
{
	//按照名字比较,两个字符串比较是不能直接相减,用库函数strcmp进行比较
	//强制类型转换为结构体指针,然后再->找到结构体成员变量name
	return strcmp(((Stu*)s1)->name , ((Stu*)s2)->name);//由于我们自己使用时知道了是什么类型,因此强转为该类型就可,
	//得到其地址再对其解引用就可以相互进行比较了
}

int main()
{
	Stu s[3] = { {"zhangsan",20},{"wangwu",30},{"lisi",50} };
	qsort(s, sizeof(s)/sizeof(s[0]), sizeof(s[0]), comper_stu_by_name);
	for (int i = 0; i < sizeof(s)/sizeof(s[0]); i++)
	{
		printf("%s %d\n", s[i].name, s[i].age);
	}
}

在这里插入图片描述
strcmp比较字符串函数
在这里插入图片描述
在这里插入图片描述

strcmp返回类型为int
qsort可以实现任意类型的数据的排序;

以冒泡模拟qsort

//比较时需要比较什么类型自己可以定义,然后强转
//需要排不同类型只需要在这里更改就可以了
int comper(void* s1, void* s2)
{
	return *((int*)s1) - *((int*)s2);
}

void swap(char* buf1, char* buf2, int width)
{
	int i = 0;
	//width是数组中每个元素的字节大小,其实以我们来看,知道width就可以知道是什么类型,
	for (i = 0; i < width; i++)
	{
		//将每个字节都交换
		char tmp = *buf1;
		*buf1 = *buf2;
		*buf2 = tmp;
		buf1++;
		buf2++;
	}
}

//与qsort函数内部一致
//比较类型不明确,所有void*
void bulle_qsort( void* a, size_t sz, size_t width, int (*comper)(const void* s1, const void* s2))
{
	size_t i = 0;
	int falg = 0;
	for (int i = 0; i < sz-1; i++)
	{
		size_t j = 0; 
		for (j = 0; j < sz - 1 - i; j++)
		{
			if (comper((char*)a+j*width,(char*)a+(j+1)*width)>0)//实现比较,交换,且由于不知道要比较什么类型,,那么我们只有使用偏移量比较
			{
				swap((char*)a + j * width, (char*)a + (j + 1) * width, width);//由于不知道类型,那么就交换每个字节,把每个元素大小传过去
				falg = 1;
			}
		}

		if (falg == 0)
		{
			break;
		}
	}
}

int main()
{
	int a[] = { 9,8,7,6,5,4,3,2,1 };
	int sz = sizeof(a) / sizeof(a[0]);
	//这里可以排任意类型的数据,我这里以整形数组模拟
	
	bulle_qsort(a, sizeof(a) / sizeof(a[0]), sizeof(a[0]), comper);
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", a[i]);
	}
	return 0;
}

在这里插入图片描述
冒泡模拟实现qsort就到这里了,有兴趣的小伙伴可以区试试其他类型的排序吧

相关文章:

  • 浏览器主页被hao123劫持的解决方案
  • C++单例模式实现
  • java八股系列——依赖注入的方式
  • 前端基础知识
  • MDK Keil5 创建Stm32工程-理论篇(这里以Stm32F103Zet6为例)
  • 电路模型和电路定律(2)——“电路分析”
  • C++中的利器——模板
  • Python绘图
  • 【Linux】-- 基本指令
  • 核心 Android 调节音量的过程
  • 微信小程序this指向问题
  • synchronized从入门到踹门
  • 运算符——“Python”
  • Nginx的搭建与核心配置
  • Stream——数字类型的字符串排序
  • 【402天】跃迁之路——程序员高效学习方法论探索系列(实验阶段159-2018.03.14)...
  • 345-反转字符串中的元音字母
  • Apache的基本使用
  • C++类的相互关联
  • ES6核心特性
  • Fundebug计费标准解释:事件数是如何定义的?
  • iOS动画编程-View动画[ 1 ] 基础View动画
  • JavaScript学习总结——原型
  • js对象的深浅拷贝
  • ReactNative开发常用的三方模块
  • SAP云平台里Global Account和Sub Account的关系
  • Spring技术内幕笔记(2):Spring MVC 与 Web
  • vue从创建到完整的饿了么(18)购物车详细信息的展示与删除
  • WinRAR存在严重的安全漏洞影响5亿用户
  • 对话 CTO〡听神策数据 CTO 曹犟描绘数据分析行业的无限可能
  • 多线程 start 和 run 方法到底有什么区别?
  • 函数式编程与面向对象编程[4]:Scala的类型关联Type Alias
  • 买一台 iPhone X,还是创建一家未来的独角兽?
  • 容器化应用: 在阿里云搭建多节点 Openshift 集群
  • 深度学习中的信息论知识详解
  • 限制Java线程池运行线程以及等待线程数量的策略
  • 移动端唤起键盘时取消position:fixed定位
  • 用mpvue开发微信小程序
  • 翻译 | The Principles of OOD 面向对象设计原则
  • ​你们这样子,耽误我的工作进度怎么办?
  • ###51单片机学习(1)-----单片机烧录软件的使用,以及如何建立一个工程项目
  • (52)只出现一次的数字III
  • (C语言)逆序输出字符串
  • (八)Docker网络跨主机通讯vxlan和vlan
  • (笔试题)分解质因式
  • (六)Hibernate的二级缓存
  • (亲测成功)在centos7.5上安装kvm,通过VNC远程连接并创建多台ubuntu虚拟机(ubuntu server版本)...
  • (数据结构)顺序表的定义
  • (万字长文)Spring的核心知识尽揽其中
  • (一)u-boot-nand.bin的下载
  • (转)JAVA中的堆栈
  • (转)shell中括号的特殊用法 linux if多条件判断
  • ... 是什么 ?... 有什么用处?
  • ..thread“main“ com.fasterxml.jackson.databind.JsonMappingException: Jackson version is too old 2.3.1
  • .NET Core WebAPI中使用Log4net 日志级别分类并记录到数据库