c语言函数指针练习---------模拟实现qsort函数

(Hello小伙伴们大家好呀,今天我们来回顾一下快速排序,在此之前让我们一起回忆 一下冒泡排序吧。)

一.冒泡排序

什么是冒泡排序呢?

我们可以简单的理解为两个两两相邻的元素进行比较,最终排成升序或降序,以升序为例如果较前的数大于较后的数(在数组范围内) ,那进行交换以此类推。

如图所示:(最后0是不需要排,在9位数拍好后0自然而然就排到了第一位)

代码思想:

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
//模拟实现冒泡排序
void bubble_sort(int str[], int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)//排几趟
	{
		int j = 0;
		for (j=0;j<sz-1-i;j++)//一趟多少次
		{
			if (str[j] > str[j + 1])
			{
				int tmp = str[j];
				str[j] = str[j + 1];
				str[j + 1] = tmp;
			}
		}
	}
}
void print_arr(int str[], int sz)
{
	int i = 0;
	for (i = 0; i < sz ; i++)
	{
		printf("%d ", str[i]);
	}
	printf("\n");
}
  int main()
{
	int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	print_arr(arr, sz);
	bubble_sort(arr, sz);
	print_arr(arr, sz);
	return 0;
}

二.qsort函数模拟实现

  (在写好冒泡排序后,我们发现一些缺陷,参数是固定的,只能是整数类型,并不通用。

    最终找到qsort函数它是用来排序任何类型的数据)

(一).qsort函数的详解:

1.qsort函数的原型:

void qsort (void* base, 

                 size_t num,

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

               );

有四个参数

(1). base:指针指向待排序数组的第一个元素

   void*base:只不过被转化为void*类型的指针也就是说传给qsort待排序数组的第一个元素的地址(起始地址)。也就穿个数组名即可。

(2).size_t num:待排序数组的元素个数

(3).size_t size:待排序数组中每个数组的每个元素的大小(字节)

  sizeof来计算即可。

(4).int (*compar)(const void*,const void*):首先这是一个函数指针,函数指针cmp指向的是一个函数,这个函数是用来比较两个元素的大小。

由于它可以排序任何类型,不同类型比较有所差异

排序整型数组:做差使用>比较

排序结构体数组:可能不能用>比较,因为要根据成员,例如年龄可以用>,姓名因为是字符我们可以用strcmp比较

(5).两个复杂类型的数据进行比较,方法不同。

我们可以可以把cmp单独拿出来,自己提供比较的方法。

(6).头文件:#include<stdlib.h>

(二).void *的理解:

 Void*指针,它不能够进行解引用,因为对它解引用操作它也不知道访问多少个字节,也不能+-整数的操作

 Void*类型的指针是用来任意类型数据的地址,就像个垃圾桶。

(三).qsort函数代码实现:

   1.整型比较

 void print_arr(int str[], int sz)
  {
	  int i = 0;
	  for (i = 0; i < sz; i++)
	  {
		  printf("%d ", str[i]);
	  }
	  printf("\n");
  }
  
  //测试qsort两个整型比较
#include<stdlib.h>
  int cmp_int(const void* e1, const void* e2)
  {
      //e1,e2存放的是需要比较两个元素的地址
	  //整型比较,强制转换  (int*)e1先强转,*(int*)e1再解引用
	  return *(int*)e1 - *(int*)e2;
	  //有三种结果 >0返回>0的数 =0返回0  <0返回<0的数
	  
 }
 void test1()
  {
	  int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
	  int sz = sizeof(arr) / sizeof(arr[0]);
	  print_arr(arr, sz);
	  qsort(arr,//数组名首元素的地址
		  sizeof(arr) / sizeof(arr[0]),//元素个数
		  sizeof(arr[0]),//一个元素大小
		  cmp_int //整型比较的函数,自己提供,返回类型一致                          
		  );
	  print_arr(arr, sz);
	  
  }
  int main()
  {
	  test1();
	  return 0;
  }

2.测试qsort排序结构体数据

  (1)对名字进行比较

 struct stu
  {
	  char name[20];
	  int age;
  };
//比较名字
#include<stdlib.h>
#include<string.h>//strcmp
  int cmp_stu_by_name(const void* e1, const void* e2)
  {
	  //先强制类型转换再结构体指向成员
	  //比较的是两个字符串的大小,用strcmp
	  //strcmp返回类型为Int和qsort一样直接返回
	  return strcmp(((struct stu*)e1)->name, ((struct stu*)e2)->name);
	 
  }
 void test2()
 {
	 struct stu arr[] = { {"zhangsan",18},{"lisi",2},{"wangwu",24} };//结构体数组,学生信息
	 int sz = sizeof(arr) / sizeof(arr[0]);
	 qsort(arr,//数组名首元素的地址
		 sizeof(arr) / sizeof(arr[0]),//元素个数
		 sizeof(arr[0]),//一个元素大小
		 cmp_stu_by_name                           
	 );

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

(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 test3()
 {
	 struct stu arr[] = { {"zhangsan",18},{"lisi",2},{"wangwu",24} };//结构体数组,学生信息
	 int sz = sizeof(arr) / sizeof(arr[0]);
	 qsort(arr,//数组名首元素的地址
		 sizeof(arr) / sizeof(arr[0]),//元素个数
		 sizeof(arr[0]),//一个元素大小
		 cmp_stu_by_age
	 );

 }
  int main()
  {
	  //test1();
	  //test2();
	  test3();
	  return 0;
  }

文章最后,如有知识点错误恳请小伙伴们指出,希望大家可以动动发财的小手手帮阿莹一键三连,阿莹万分感激!

  • 10
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值