首页 > 其他分享 >深⼊理解指针(5)[回调函数、qsort相关知识(qsort可用于各种类型变量的排序)】

深⼊理解指针(5)[回调函数、qsort相关知识(qsort可用于各种类型变量的排序)】

时间:2024-11-12 17:46:26浏览次数:3  
标签:arr 函数 int void qsort char 排序 指针

  目录 1. 回调函数 2. qsort相关知识(qsort可用于各种类型变量的排序)

一      回调函数

     1定义/作用:把函数的指针(地址)作为参数传递给另⼀个函数,当这个指针被⽤来调⽤其所指向的函数 时,被调⽤的函数就是回调函数。回调函数不是由该函数的实现⽅直接调⽤,⽽是在特定的事件或条件发⽣时由另外的⼀⽅调⽤的,(作用)⽤于对该事件或条件进⾏响应。

    2好处:(下面我们来看两个效果相同的代码,比较它们的简约程度)

代码1(未使用回调函数

 

 代码2(使用回调函数

 总结:这里我们使用回调函数,使得重复得部分得到了优化,代码变得更加简约。

二      qsort相关知识

1形式:

void qsort
(
     void* base//base->待排序数组中的首元素
     size_t num//待排序数组中的元素个数因为元素个数不可能是负数所以用size_t定义
     size_t size//待排序数组中的一个元素的大小因为一个元素的大小不可能是负数所以用        size_t定义
    int* (*cmp)(const void*,const void*)//函数指针--指针指向的函数,可用于比较base指向的数组中任何两个元素的大小。  因为用于比较的数组类型不同所以用void定义,又因为我们只对数据进行排序而不对数据进行改变所以用const修饰,防止数据被改写
    
)

2   qsort 使⽤举例

2.1使⽤qsort函数排序整型数据

#include <stdio.h>
//qosrt函数的使⽤者得实现⼀个⽐较函数

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

int main()
{
   int arr[] = { 1, 3, 5, 7, 9, 2, 4, 6, 8, 0 };
   int i = 0;
   qsort(arr, sizeof(arr) / sizeof(arr[0]), sizeof (int), int_cmp);

for (i = 0; i< sizeof(arr) / sizeof(arr[0]); i++)
{
   printf( "%d ", arr[i]);
}

printf("\n");
return 0;
}

2.2使⽤qsort函数排序结构数据(要指明排序类型例如描述一个人是使用结构体可能含有姓名,性别等,这时候就要指明你要排序的数据如要对姓名就要指明姓名)

按照名字来排序

 注意在按照名字进行比较时和整型有所不同,因为名字是字符串,要用strcmp函数。

按照年龄来⽐较

2.3 qsort函数的模拟【实现使⽤回调函数,模拟实现qsort(采⽤冒泡的⽅式)】。

主体框架

注意我们这里要模仿qsort函数,对其冒泡排序设置参数

排序的实现

 注意这里和冒泡排序有所不同的是在于冒泡排序只对整型排序直接比较即可,而我们这里比较两个元素的大小是通过字符类型来比较因为每个整数数组中的元素都是占4个字节,所以要用强制类型转换将其转换为char*型,而这里的width表示的是整型数组中一个元素的长度,所以这里的(char*)base + j * width,和(char*)base+(j + 1) * width表示第j个元素和第j+1个元素

函数的声明

实现交换

因为一个整型占4个字节无法进行交换,这时候我们将其划分为一个一个字节,将其强制类型转换为字符型char*,然后我们只要将两个元素的4个字节一一交换即可。

 这里的n表示的是width(4),因为一个整型占4个字节,而我们前面将其强制类型转换为字符型char*,这时候我们只要将两个元素的4个字节一一交换即可。

整体代码

#include <stdio.h>

int cmp_int(const void* e1, const void* e2)
{
	return *(int*)e1 - *(int*)e2; 
}

void swap(char* buf1, char* buf2, size_t n)
{
	int i = 0;
	for (i = 0; i < n; i++)
	{
		char tmp = *buf1;
		*buf1 = *buf2;
		*buf2 = tmp;
		buf1++;
		buf2++;
	}
}

void bubble_sort(void* base, size_t sz, size_t width, int (*cmp)(const void* e1, const void* e2))
{
	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 print(int arr[], int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
}
void test()
{
	int arr[] = { 9,8,7,6,5,4,3,2,1,10};
	int sz = sizeof(arr) / sizeof(arr[0]);
	bubble_sort(arr, sz, sizeof(arr[0]), cmp_int);//模仿qsort函数,对其设置参数
	print(arr, sz);//打印
}
int main()
{
	test();

	return 0;

}

    本篇文章就到此结束,希望有所能帮到 读者更好的了解指针。

标签:arr,函数,int,void,qsort,char,排序,指针
From: https://blog.csdn.net/2301_78901562/article/details/143675071

相关文章

  • C++笔记---智能指针
    1.什么是智能指针1.1 RALL设计思想RAII(ResourceAcquisitionIsInitialization,资源获取即初始化)是一种资源管理类的设计思想,广泛应用于C++等支持对象导向编程的语言中。它的核心思想是将资源的管理与对象的生命周期紧密绑定,通过在对象的构造函数中获取资源,并在析构函数中......
  • 高级语言调用C接口(一)基础类型与基础类型指针的对应关系
    基础类型C变量类型Java变量类型C#变量类型python变量类型arkts变量类型备注intintintc_intnumberunsignedintlonguintc_uintnumbershortshortshortc_shortnumberunsignedshortintushortc_ushortnumberlongintintc_longnumber32位系统中,C中的long型占4字节,可以当作in......
  • 排序算法 -堆排序
    文章目录1.堆排序(HeapSort)1.1简介1.2堆排序的步骤1.3堆排序C语言实现1.4时间复杂度1.5空间复杂度1.堆排序(HeapSort)1.1简介堆是一种特殊的完全二叉树,分为最大堆(MaxHeap)和最小堆(MinHeap)。在最大堆中,每个节点的值都大于或等于其子节点的值;在最小堆中,每个......
  • 数据结构——快速排序
    目录一、排序思想二、代码实现(一)hoare版1、原版——固定选key2、随机选key、三数取中选key(二)挖坑法(三)前后指针法(四)小区间优化(五)非递归写法一、排序思想任取待排序元素序列中的某元素作为基准值,按照该基准值将待排序集合分割成两子序列,左子序列中所有元素均小于基......
  • This指针,static(静态成员)
    一、this指针    一个对象由属性(数据)和行为(函数)组成。    每个对象都只存储了自己的数据成员,并没有保存函数。例如,sizeof(d1)==4;    成员函数存储于.text(代码段),只保存一份,则同类型的对象共用。this的类型为:类名*const(例如:Demo*const)问题......
  • python算法之最low三人组之一——————选择排序
    之前讲过了冒泡排序,我们再聊一聊最low三人组中的选择排序,选择排序的基本思想是:遍历整个序列,选取其中一个最小的数取出来,然后再次遍历除了刚刚选出来的最小的数的序列中最小的数现在让我们看看代码实现importrandomdefselect_sort(li):new_li=[]foriinrange(l......
  • 快速排序,思路总结与实现
    思路找基准值(pivot)pivot=startorend比基准值小的放左边,大的放右边实现双指针,left从左到右找比基准值大的元素,right从右到左找比基准值小的元素找到后交换left和right指针的内容直到left=right这是递增排序,递减排序情况相反如果pivot=start,则右指针先动,否......
  • 算法学习—归并排序
    1.算法介绍 归并算法是一种由冯·诺伊曼发明的分治算法,相较于普通排序算法时间复杂度较低,运行效率高。通常情况下,归并算法的时间复杂度为O(nlogn)。2.算法思想以及大致步骤 归并算法主要运用到了分治以及归并的思想,主要步骤如下:首先将一个无序数组分为n个有序的单个数......
  • 算法学习—快速排序
    1.算法介绍   快速排序算法是一种高效排序算法,效率相比普通排序算法较高,通常情况下时间复杂度为O(nlogn),但在最坏情况下时间复杂度会提高到O(n^2)2.算法思想和大致步骤 快速排序算法主要用到了二分和递归的思想,主要有三个步骤:(1)在数组中选取一个元素作为基准值(pivot)......
  • 十大经典排序算法-插入排序
    插入排序的代码实现虽然没有冒泡排序和选择排序那么简单粗暴,但它的原理应该是最容易理解的了,因为只要打过扑克牌的人都应该能够秒懂。插入排序是一种最简单直观的排序算法,它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。插入排......