qsort函数的简单使用

简介: ① qsort 是一个库函数,头文件是 <stdlib.h>.② qsort 是基于快速排序算法的排序函数。

引言



① qsort 是一个库函数,头文件是 <stdlib.h>.

② qsort 是基于快速排序算法的排序函数。


一、了解qsort函数



void qsort (void* base, // 1
            size_t num, // 2 
            size_t size, // 3        
            int (*compare)(const void* a,const void* b)); // 4
// 1. base 表示的是数组首元素的地址,一般为数组名
// 2. num 表示的是数组中元素的个数
// 3. size 表示的数组中每个元素所占内存的字节大小
// 4. compare 表示一个函数指针,指向自定义函数的地址。也就是说,使用什么样的自定义函数,直接传过来给 qsort 调用即可。


注意事项:


① compare 参数可以这么做:我们自己进行创建的一个函数 function,然后把 function 的地址作为 qsort 的 compare 参数。(这需要理解函数指针的知识,如果不理解也没关系,直接传函数名,也可以表示函数的地址)


② 自定义函数的形参为 a 和 b,它们都是 void* 指针类型。这么设计的原因就是:待排序的数据不确定,(可能是整型、浮点型、字符…)。后期在自定义函数中,先强制转换,再解引用也可以很好地比较元素。


二、使用qsort函数对数组中的各种类型进行排序



1. 整型元素排序


#include <stdio.h>
#include <stdlib.h>
int compare(const void* a, const void* b);
int main(void) 
{
  int arr[] = { 9,7,8,4,5,6,1,2,3,0 };
  int sz = sizeof(arr) / sizeof(arr[0]);
  qsort(arr,sz, sizeof(int), compare);
  int i = 0;
  for (i = 0; i < sz; i++)
  {
    printf("%d ", arr[i]);
  }
  printf("\n");
  return 0;
}
int compare(const void* a, const void* b)
{
  return (*(int*) a - *(int*) b);
}
//解释  qsort(arr,sz, sizeof(int), compare);
//1. arr是数组名,表示首元素的地址
//2. sz表示数组中所有元素的个数,这里sz = 10
//3. sizeof(int)是计算数组中的每个元素是多少字节的
//经计算后是4个字节,或者写成 sizeof(arr[0])
//4. compare表示我们自己创建的一个函数
//规则就是接收两个无符号指针类型,目的在于排序任何类型的变量
//5. 解释  return (*(int*) a - *(int*) b);
//(1)将其先强制转换成int* 指针,目的是确定元素的类型为 int
//(2)再解引用,目的是通过指针找到数组中的元素
//(3)最后返回


输出结果:


f2d0c1e681294c989170d19f51f2d27a.png


注:如果我们把a和b调换位置,那么就会进行降序操作


#include <stdio.h>
#include <stdlib.h>
int compare(const void* a, const void* b);
int main(void) 
{
  int arr[] = { 9,7,8,4,5,6,1,2,3,0 };
  int sz = sizeof(arr) / sizeof(arr[0]);
  qsort(arr,sz, sizeof(int), compare);
  int i = 0;
  for (i = 0; i < sz; i++)
  {
    printf("%d ", arr[i]);
  }
  printf("\n");
  return 0;
}
int compare(const void* a, const void* b)
{
  return (*(int*) b - *(int*) a);
}


输出结果:


034b012300a74819a066608aecfc7e2f.png


2. 字符串中的字符元素排序


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int compare(const void* a, const void* b);
int main(void)
{
  char arr[] = "adgcefb";
  int len = strlen(arr);
  qsort(arr, len, sizeof(char), compare);
  printf("%s\n", arr);
  return 0;
}
int compare(const void* a, const void* b)
{
  return strcmp((char*)a, (char*)b); 
  //用strcmp比较字符串
}
//解释  qsort(arr, len, sizeof(char), compare);
//1. arr是数组名,表示首元素的地址
//2. len表示数组中待排序的字符的格式,不包括'\0'
//3. sizeof(char)是计算数组中的每个元素是多少字节的,经计算后是1个字节
//或者写成sizeof(arr[0])
//4. compare表示我们自己创建的一个函数
//规则就是接收两个无符号指针类型,目的在于排序任何类型的变量
//5. 解释  return strcmp((char*)a, (char*)b);
//(1)将其先强制转换成char* 指针,目的是确定元素的类型为 char
//(2)再解引用,目的是通过指针找到数组中的元素
//(3)最后返回
//这里用到了strlen函数和strcmp函数,不再展开讲


注:如果我们把a和b调换位置,那么仍然会进行降序操作


3. 结构体元素排序


1. 排序结构体中的字符


(1) 我们先创建一个 struct stu 类型的结构体,里面分别有名字、年龄、成绩 这三个变量

(2) 之后创建一个结构体数组,即用数组装了三个结构体变量

(3) 下面代码,目的是为了把人的名字进行排序,然后展示出来


这就好像我们大一在学校一样,用姓氏来排名

所以我创建了一个 comparebyname 函数进行排序


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int comparebyname(const void* a, const void* b);
struct stu
{
  char name[20];
  int age;
  float grade;
};
int main(void)
{
  struct stu arr[3] = { {"mingming",23,85}, {"yueyue", 20, 87},{"lili", 26, 90} };
  int sz = sizeof(arr) / sizeof(arr[0]);
  int i = 0;
  for (i = 0; i < sz; i++)
  {
    printf("%-15s %-10d %-10f\n", arr[i].name, arr[i].age, arr[i].grade);
  }
  printf("\n");
  qsort(arr, sz, sizeof(struct stu), comparebyname);
  for (i = 0; i < sz; i++)
  {
    printf("%-15s %-10d %-10f\n", arr[i].name, arr[i].age, arr[i].grade);
  } 
  return 0;
}
int comparebyname(const void* a, const void* b)
{
  return strcmp(((struct stu*)a)->name, ((struct stu*)b)->name);
}
//解释  qsort(arr, sz, sizeof(struct stu), comparebyname)   
//1. arr是数组名,表示首元素的地址
//2. sz表示数组中所有元素的个数,这里sz = 3
//3. sizeof(struct stu)是计算数组中的每个元素是多少字节的,经计算后的值是28个字节
//(结构体内存对齐)
//这里的数组中每个元素是结构体变量,所以就是这么求得的,或者写成sizeof(arr[0])
//4. comparebyname表示创建一个函数,规则就是以字符串的首字符来进行排序整个数组
//5. return strcmp(((struct stu*)a)->name, ((struct stu*)b)->name);
//(1) (struct stu*)a 将无符号指针强制转换成一个结构体指针,目的是确定元素的类型
//(2) ((struct stu*)a)->name 访问结构体成员变量
//(3) strcmp()接收的是两个地址,也就是指针类型
//(4) 这其中的name表示的是数组首元素的地址,所以符合strcmp要求


输出结果:


字符升序

l - m - y


24d8f15fc29048868a69a1583da2efc9.png


同一个想法,不同逻辑

接着,我使用以年龄为排序方式


2. 排序结构体中的整型


同理,我创建了一个 comparebyage 函数


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int comparebyage(const void* a, const void* b);
struct stu
{
  char name[20];
  int age;
  float grade;
};
int main(void)
{
  struct stu arr[3] = { {"mingming",23,85}, {"yueyue", 20, 87},{"lili", 26, 90} };
  int sz = sizeof(arr) / sizeof(arr[0]);
  int i = 0;
  for (i = 0; i < sz; i++)
  {
    printf("%-15s %-10d %-10f\n", arr[i].name, arr[i].age, arr[i].grade);
  }
  printf("\n");
  qsort(arr, sz, sizeof(struct stu), comparebyage);
  for (i = 0; i < sz; i++)
  {
    printf("%-15s %-10d %-10f\n", arr[i].name, arr[i].age, arr[i].grade);
  }
  return 0;
}
int comparebyage(const void* a, const void* b)
{
  return (*(struct stu*)a).age - (*(struct stu*)b).age;
}
//解释  qsort(arr, sz, sizeof(struct stu), comparebyage)  
//1. arr是数组名,表示首元素的地址
//2. sz表示数组中所有元素的个数,这里sz = 3
//3. sizeof(struct stu)是计算数组中的每个元素是多少字节的,经计算后的值是 28个字节
//这里的数组中每个元素是结构体变量,所以就是这么求得的,或者写成sizeof(arr[0])
//4. comparebyage表示创建一个函数,规则就是以成绩的大小来进行排序整个数组
//5. return (*(struct stu*)a).age - (*(struct stu*)b).age;
//(1) (struct stu*)a 将无符号指针强制转换成一个结构体指针,目的是确定元素的类型为 
//(2) (*(struct stu*)a).age 访问结构体成员变量
// age 是一个整型变量,所以必须解引用指针,然后访问的才是元素
//(3) 两个整型,在这qsort逻辑里面,直接用减号比较,然后返回就行了


输出结果:


数字升序

20 - 23 - 26


5f1590840a3b418cb178fcb9bd1673eb.png


总结



1. 本文意在表达如何正确、简单地使用qsort函数,并不打算介绍 qsort 函数内部算法的功能。qsort 函数是基于升序算法的,感兴趣的小伙伴可以模拟一下函数。


2. 本文没有讲到浮点类型的排序,因为它的逻辑和整形元素其实是一样的。


3. 本文用到了字符串函数,有如strlen、strcmp,这些并没有展开讲,不熟悉的小伙伴可以去MSDN,或者 cplusplus.com 去看一下,本文的 qsort函数 详细说明也可以看到介绍。


4. 本文也用到了数组、指针、结构体的一些知识,并将它们串了起来,对复习之前的C语言知识还是有亿点点帮助的,哈哈哈。


image.jpeg


Over. 谢谢观看哟~

目录
相关文章
|
4月前
|
C语言
c语言进阶部分详解(经典回调函数qsort()详解及模拟实现)
c语言进阶部分详解(经典回调函数qsort()详解及模拟实现)
58 0
for循环的基本使用
For循环摘要: - For循环控制代码段重复执行。 - 格式: `for(初始化; 条件; 更新){ 循环体; }` - 流程: 1. 初始化变量。 2. 检查条件,若真,则执行循环体。 3. 更新变量。 4. 再次检查条件,决定是否继续循环。 - 循环按1→2→3→4顺序执行,直至条件不满足。 注:以上内容未包含图片信息。
|
4月前
|
存储 编译器
数组应该怎么用?
数组应该怎么用?
20 1
|
4月前
|
搜索推荐 C语言 索引
【C语言】剖析qsort函数的实现原理
【C语言】剖析qsort函数的实现原理
67 0
qsort函数和模拟实现qsort函数
qsort函数和模拟实现qsort函数
|
11月前
|
算法 程序员 C语言
【进阶C语言】排序函数(qsort)与模拟实现(回调函数的实例)
回调函数为C语言重要知识点,以函数指针为主要知识;下面介绍回调函数的定义、回调函数的库函数举例即库函数模拟实现。
39 0
【进阶C语言】排序函数(qsort)与模拟实现(回调函数的实例)
|
11月前
|
编译器 C语言
C语言之回调函数,qsort函数的定义及使用方法
C语言之回调函数,qsort函数的定义及使用方法
|
算法 C语言
【C语言进阶篇】回调函数都学了吧!那么用冒泡排序实现qsort函数你会嘛?
【C语言进阶篇】回调函数都学了吧!那么用冒泡排序实现qsort函数你会嘛?
74 0
|
C语言
【c语言进阶】还在自己写排序的函数吗?快来通过回调函数学习并模拟库函数 qsort 的实现把
【c语言进阶】还在自己写排序的函数吗?快来通过回调函数学习并模拟库函数 qsort 的实现把
48 0
|
C语言
C语言-qsort函数基本使用
C语言-qsort函数基本使用
76 0