保姆级教程——qsort到底怎用

并不是很重要的废话

qsort到底是什么

(不过是一个 头文件是<stdlib.h>的用于排序的超好用的函数罢辽)

先放一个函数原型压压惊

void qsort( void *ptr, size_t count, size_t size,
            int (*comp)(const void *, const void *) );

看不懂也没关系,稍后会进行分解


看看就行系列

  • 在c的文档里,对qsort是这样描述的
    在这里插入图片描述
    翻译一下重点就是,qsort函数是按升序对给定数组进行排序,而原型中出现的函数用于对象的比较。
  • 再看看文档对原型中出现的comp函数是怎么解释的
    在这里插入图片描述
    下面会进行详解,这里就不翻译啦

这才是正文

详解函数原型

void qsort( void *ptr, size_t count, size_t size,
            int (*comp)(const void *, const void *) );

qsort的函数原型包含四部分,分别是:

  • 指向待排序数组的指针(使用的时候传个地址进去哦)
  • 数组里元素的数量
  • 数组中每个元素的大小
  • 比较函数(这个在下面单独讲解)

举个例子

//假设现在有一个数组 a
int a[] = { 2,5,3,6,1,4 };
//将要对a进行排序,那么在调用qsort的时候就是这样的
qsort(a, 6, 4, comp);
//但是其实我更喜欢写成👇这个样子
qsort(a, sizeof(a) / sizeof(a[0]), sizeof(int), comp);
  • 第一个a,自然就是数组a的地址
  • 第二个6,是指数组a里面现在有6个数字
  • 第三个4,是在64位机上,int类型占用4个字节(所以直接sizeof(int),不用记类型的大小更方便)
  • 第四个函数马上就说

详解comp

来看看这个嵌在qsort原型里面的comp原型

 int (*comp)(const void *, const void *);

comp存在的意义

每个函数都有它存在的意义。而这个comp的意义,就是用于对象的比较。说白了,我们要通过编写comp函数来决定qsort如何对数组进行排序。

comp的作用途径

总结一下文档里的描述,用人话说就是

  • 如果comp返回正整数,那么qsort会交换传入的两个元素的位置

  • 如果comp返回负整数,那么qsort不会交换传入的两个元素的位置

而我们编写comp就是在决定什么时候要交换位置,什么时候不交换位置
所以学会使用qsort最关键的就是学会编写comp

comp到底应该怎么写

总结一下就两步

  1. 强制转换指针的类型
  2. 在某种情况下返回整数值

举个例子(这个排出来是降序哦)

int compare(const void* a, const void* b) {
	//第一步强制转换
	int* pa = (int*)a;
	int* pb = (int*)b;
	//第二步根据想交换的情况返回值
	if (*pa < *pb) {
		return 1;
	}
	else {
		return -1;
	}
 }
  • comp其实就是一个函数,叫什么无所谓(不一定叫comp,像例子里叫compare也是可以的)
  • 记得一定一定要对指针进行类型的转换,因为传进来的时候,类型是void
  • 在返回的时候,有些会习惯写成return *pa-*pb;的形式,但是这种形式要注意的小点比较多,而且不够清晰,本篇博客就不用这种形式写了

一大波例子正在靠近

对double型数组进行排序

double a[] = { 1.0,4.2,6.3,3.0,5.0,8.0,9.0,6.4 };

int compare(const void* a, const void* b) {
	double* pa = (double*)a;
	double* pb = (double*)b;
	if (*pa < *pb) {
		return 1;
	}
	else {
		return -1;
	}
}

不能写成return *pa - *pb;
因为返回类型是int,这样相减的结果会被强制转换成int,导致结果出错
比如上面这个例子,运行的结果会是👇
在这里插入图片描述

对字符串指针数组进行排序

char* a[4] = { (char*)"hi", (char*)"happy", (char*)"in", (char*)"3g" };

int compare(const void* a, const void* b) {
	char* pa = *(char**)a;
	char* pb = *(char**)b;
	return strcmp(pa, pb);
}

一般对字符串排序都是从小到大,如果pa<pb,strcmp会返回负数,qsort不会进行交换,恰好满足了需求,直接返回strcmp结果就行。

对结构体数组一级排序

typedef struct people {
	int num1;
	int num2;
}People;
People a[3] = { {1,2},{3,6},{3,5}};

int compare(const void* a, const void* b) {
	People* pa = (People*)a;
	People* pb = (People*)b;
	if (pa->num1 < pb->num1)  return -1;
	else   return 1;
}

对结构体数组进行二级排序

typedef struct people {
	int num1;
	int num2;
}People;
People a[3] = { {1,2},{3,6},{3,5}};

int compare(const void* a, const void* b) {
	People* pa = (People*)a;
	People* pb = (People*)b;
	if (pa->num1 < pb->num1) {
		return -1;
	}
	else if (pa->num1 > pb->num1) {
		return 1;
	}
	else {
		if (pa->num2 < pb->num2) {
			return -1;
		}
		else {
			return 1;
		}
	}
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值