首页 > 其他分享 >qsort函数[3]---冒泡排序与qsort函数的结合

qsort函数[3]---冒泡排序与qsort函数的结合

时间:2024-03-16 15:59:49浏览次数:25  
标签:sz arr 函数 int void qsort 冒泡排序

冒泡排序与qsort函数的结合

首先给大家回顾一下冒泡排序

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 - i - 1; j++)
		{
			if (arr[j] < arr[j + 1])
			{
				int tmp = arr[j + 1];
				arr[j + 1] = arr[j];
				arr[j] = tmp;
			}
		}
	}
}

冒泡排序就是在一个有序数组内部两两相邻元素进行比较。

而它与qsort函数将擦出什么样的火花呢?

qsort函数结构

首先我们先回忆以下qsort函数的结构

qsort(void*base, size_t sz, size_t width, int (*compar)(const void*,const void*)

void*base: 需要比较的数组元素的地址.

size_t sz: 需要比较的数组元素个数.

size_t width:数组中每个元素的大小(单位是字节)

int (*compar)(const void*,const void*) :用来调用比较函数compar是函数名 后面的两个参数分别是数组中两个被比较元素的指针

冒泡函数的结构

bubble_sort(int arr[],int sz)

int arr[] :需要比较的目标数组

int sz:数组中的元素个数

结合思路

冒泡排序实现思路

冒泡排序的思路就是根据数组元素的数量确定需要排序的趟数,以及每趟两两排序的次数,而确定趟数思路就是用元素个数减一,而确定排序次数则是每次比较都会比上一次少一次,所以只需要在趟数的for循环下面再次嵌套一个for循环减去趟数在减去一便是次数,根据这个思路我们可以确定需要传的参数有数组地址数组内元素个数,以及数组每个元素的大小,用来找下一个元素

qsort函数特点

首先我们知道qsort函数的底层逻辑是快速排序,既可以排序字符串也可以排序整形元素,结构体,其中需要改变的只有需要调用的用来比较的函数。

代码展示

将qsort函数参数换到冒泡排序

void bubble_sort(void* base, size_t sz, size_t width, int(*cmp)(const void* p1, const void* p2))
{
	//确定趟数
	int i = 0;
	for (i = 0; i < sz - 1; i++)
	{
		//每趟进行两两互相比较
		int j = 0;
		for (j = 0; j < sz - i - 1; j++)
		{
			if (cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0)
			{
				swap((char*)base + j * width, (char*)base + (j + 1) * width, width);
			}
		}
	}
}

交换代码块

void swap(char* c1, char* c2, size_t width)
{
	int i = 0;
	for (i = 0; i < width; i++)
	{
		char tmp = *c1;
		*c1 = *c2;
		*c2 = tmp;
		c1++;
		c2++;
	}
}

冒泡排序中if条件判断代码块

int cmp_int(const void* p1, const void* p2)
{
	return *(int*)p1 - *(int*)p2;
}

主函数以及test函数

void test1()
{
	int arr[] = { 2,1,6,4,3,5,8,9,0,7 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	bubble_sort(arr, sz, sizeof(arr[0]), cmp_int);
	print_arr(arr, sz);
}
int main()
{
	test1();
	return 0;
}

注意

判断条件内指针类型为char*是因为有的时候需要排序元素的大小不一,我们规定了每个元素的宽度单位字节,而char*的大小是一个字节,我们只需要循环宽度的大小便可以比较的每个元素,而在交换的时候也是一个字节一个字节的交换,所以类型转换为char*。

其次我们需要注意的是在每一个函数内部如果需要调用其他函数就必须把需要调用的函数放在该函数代码块的上面,或者也可以增加函数声明,不然不能成功运行

最后如果本篇文章存在错误望指正,感谢各位大佬

标签:sz,arr,函数,int,void,qsort,冒泡排序
From: https://blog.csdn.net/weixin_74837455/article/details/136717951

相关文章

  • 函数指针数组(转移表)
    函数指针数组,首先是一个数组,其次其中存储的数据类型是函数指针,所以我们可以通过使用函数指针数组来调用不同的函数。接下来为大家展示他的基本使用方法(模拟计算器)函数指针数组结构   int(*arr[])(intx,inty)={NULL,Add,Sub,Mul,Div};其中NULL,Add,Sub,Mul,Div......
  • 字符串函数与内存函数的使用和模拟实现
    前言:字符函数与内存函数的优劣:字符函数如果处理字符相关的数据的话,用起来比较方便。相较于字符串函数,内存函数可以处理除字符外的其他类型的数据。目录1.字符串函数1.1strcpy1.2strcmp1.3strcat 1.4strncpy  strncmp strncat2.内存函数2.1memcpy 2.2......
  • 滴水逆向笔记系列-c++总结2-36.权限控制-37.虚函数-38.多态_绑定
    第三十六课c++3权限控制1.定义和实现分开写2.private和publicprivate权限说明私有变量在类外是无法访问的,只有在类内或者使用类内函数访问类内函数访问3.private真的不能访问吗反汇编看看t对象在初始化public和private成员时都是一视同仁的,在底层还是没区别,都是编......
  • 【C++函数速查】lower_bound和upper_bound使用方法详细解读
    文章目录1)概述2)函数使用3)案例代码1)概述lower_......
  • 结构体三种实例化方法(含成员函数)
    结构体成员函数三种实例化方法结构体成员函数需要定义成指针函数,定义函数,但不在结构体内实现方法,在外部(需要在函数体内部实现)结构体指针使用->符号访问结构体直接实例化使用.符号访问成员第一种:结构体直接实例化#include<stdio.h>//在此初始化结构体,内部成......
  • C++函数调用优化
    C++函数调用优化施磊老师网课笔记截图1、用临时对象拷贝构造一个新对象的时候,编译器会对其优化,直接用生成临时对象的方法构造新对象;......
  • C++ Function Templates (函数模板)
    C++FunctionTemplates[函数模板]1.TemplatesandGenericProgramming(模板与泛型编程)2.DefiningaFunctionTemplates(定义函数模板)2.1.InstantiatingaFunctionTemplate(实例化函数模板)2.2.TemplateTypeParameters(模板类型参数)2.3.Non......
  • 20240315,逻辑类型,条件和逗号,函数,数组
    刚好看到逻辑类型,今天早上有个很好玩的事情,一早上醒来圆圆的小狗跑到了床下,然后她说“你是不是打我的小狗了”我;”我没有,我什么都不知道””他的屁股都扁了“我:“我怎么知道,他的屁股扁了关我什么事"“你怎么知道他的屁股扁了”我“不是你说的嘛”“我诈你的”,然后走了......
  • C语言新手经典基础题——冒泡排序
    冒泡排序:用户输入一组数,编写程序将该组数据进行从小到大的顺序进行排列。举个例子:用户输入;1413918766这一组数据,现在要将这组数据进行从小到大的程序进行排列。我们编写程序的思路如下:现将第一个数和第二个数进行比较,即14和13,13比14小,那么就将13和14进行位置的调换,13......
  • 函数方法定义
    publicclassday_5_1{publicstaticvoidmain(String[]args){/*方法,函数什么是方法?具有特定功能的一段独立小程序方法作用?1,提高了代码的复用性2,提高了代码的维护性方法的定义格式?......