qsort函数使用方法总结(详细全面+代码)
文章目录
- 1. qsort函数原型
- 2. compar参数
- 3. int 数组排序
- 4. 结构体排序
- 5. 字符串指针数组排序
- 6. 字符串二维数组排序
- 7. qsort函数应用:整型二维数组
1. qsort函数原型
void qsort(void *base,size_t nmemb,size_t size,int (*compar)(const void *, const void *));
头文件:<stdlib.h>
函数功能:qsort()函数的功能是对数组进行排序,数组有nmemb个元素,每个元素大小为size。
参数base : base指向数组的起始地址,通常该位置传入的是一个数组名。
参数nmemb :nmemb表示该数组的元素个数
参数size :size表示该数组中每个元素的大小(字节数)
参数(*compar)(const void *, const void *)
:此为指向比较函数的函数指针,决定了排序的顺序。
函数返回值:无
注意:如果两个元素的值是相同的,那么它们的前后顺序是不确定的。也就是说qsort()是一个不稳定的排序算法。
2. compar参数
compar参数是qsort函数排序的核心内容,它指向一个比较两个元素的函数,注意两个形参必须是const void *
型,同时在调用compar 函数(compar实质为函数指针,这里称它所指向的函数也为compar)时,传入的实参也必须转换成const void *
型。在compar函数内部会将const void *
型转换成实际类型,见下文。
int compar(const void *p1, const void *p2);
如果compar返回值小于0(< 0),那么p1所指向元素会被排在p2所指向元素的前面
如果compar返回值等于0(= 0),那么p1所指向元素与p2所指向元素的顺序不确定
如果compar返回值大于0(> 0),那么p1所指向元素会被排在p2所指向元素的后面
因此,如果想让qsort()进行从小到大(升序)排序,那么一个通用的compar函数可以写成这样:
//方法一int compare (const void * a, const void * b){if ( *(MyType*)a < *(MyType*)b ) return -1;if ( *(MyType*)a == *(MyType*)b ) return 0;if ( *(MyType*)a > *(MyType*)b ) return 1;}
注意:你要将MyType换成实际数组元素的类型。
或者,如下所示。
//方法二
//升序排序int compare (const void * a, const void * b){return ( *(int*)a - *(int*)b );}
//降序排列int compare (const void * a, const void * b){return ( *(int*)b - *(int*)a );}
如果变量 a 指向一个较小的负整型数,b指向一个较大的正整型数,(*(int*)a - *(int*)b)
表达式会计算出一个正数,这是错误的。
因此,我们不能用减法来比较int的大小,这会产生溢出。取而代之地,我们可以使用大于、小于运算符来比较,如方法一所示。
3. int 数组排序
/* qsort example */
#include <stdio.h>
#include <stdlib.h> int values[] = { 40, 10, 100, 90, 20, 25 };int compare (const void * a, const void * b)
{return ( *(int*)a - *(int*)b );
}int main ()
{int n;qsort (values, sizeof(values)/sizeof(values[0]), sizeof(int), compare);for (n=0; n<sizeof(values)/sizeof(values[0]); n++)printf ("%d ",values[n]);return 0;
}
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_16933601/article/details/107214404
4. 结构体排序
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include<stdlib.h>
// void qsort(void* base, size_t num, size_t size, int(*compare)(const void*, const void*))typedef struct
{char name[30]; // 学生姓名int Chinese; // 语文成绩int Math; // 数学成绩 int English; // 英语成绩
}st;
int cmp(const void* a, const void* b)
{st* pa = (st*)a;st* pb = (st*)b;int num1 = pa->Chinese + pa->English + pa->Math;int num2 = pb->Chinese + pb->English + pb->Math;//return (int)num1 - num2; // 从小到大,return (int)num2 - num1; // 从大到小
}
int main(void)
{st students[7] = {{"周",97,68,45},{"吴",100,32,88},{"郑",78,88,78},{"王",87,90,89},{"赵",87,77,66},{"钱",59,68,98},{"孙",62,73,89}};qsort(students, 7, sizeof(st), cmp); // 注意区别 students 与 stfor (int i = 0; i < 7; i++){printf("%s%4d%4d%4d\t", students[i].name, students[i].Chinese, students[i].Math, students[i].English);printf("总分:%d\n", students[i].Chinese + students[i].English + students[i].Math);}system("pause");return 0;
}
5. 字符串指针数组排序
#include <stdio.h>
#include <string.h>
#include <stdlib.h>int compare(const void *arg1, const void *arg2);int
main(int argc, char** argv)
{int i;char *arr[5] = { "i", "love", "c", "programming", "language" };qsort(arr, sizeof(arr)/sizeof(arr[0]), sizeof(char *), compare);for (i = 0; i < 5; i++) {printf("%s ", arr[i]);}printf("\n");}int compare(const void *arg1, const void *arg2) {char *a = *(char**)arg1;char *b = *(char**)arg2;int result = strcmp(a, b);if (result > 0) {return 1;}else if (result < 0) {return -1;}else {return 0;}
}
那么我们向qsort传入arr之后,qsort将arr理解为指向数组中第一个元素的指针,所以形参表中,arg1和arg2其实是指向“指向常量字符串的指针”的指针,是char**
。而我们需要传给strcmp这个字符串比较函数的,是“指向字符串的指针”,是char*
,所以我们将void*
转换为char**
,然后解引用,得到char*
,赋予a和b。接下来使用strcmp对a和b进行比较。(数组名本身算一层指针,而里面的内容又是一层指针,数组存放的是指向字符串的地址)
6. 字符串二维数组排序
#include <stdio.h>
#include <string.h>
#include <stdlib.h>int compare(const void *arg1, const void *arg2);int
main(int argc, char** argv)
{int i;char arr[5][16] = { "i", "love", "c", "programming", "language" };qsort(arr, sizeof(arr)/sizeof(arr[0]), sizeof(arr[0]), compare);printf("%s\n", arr[0]);for (i = 0; i < 5; i++) {printf("%s ", arr[i]);}printf("\n");
}int compare(const void *arg1, const void *arg2) {char *a = (char*)arg1;char *b = (char*)arg2;int result = strcmp(a, b);if (result > 0) {return 1;}else if (result < 0) {return -1;}else {return 0;}
}
这里对二维数组进行排序,其实是对二维数组的第二维中存放的字符串进行排序。所以qsort(arr, sizeof(arr)/sizeof(arr[0]), sizeof(arr[0]), compare);
对qsort函数的调用中,第二个参数是待排元素的个数(5个),第三个参数是待排元素的大小(16)。
我们将arr传入qsort函数,qsort函数将arr理解为指向数组第一个元素的指针,arr的第一个元素是arr[0][0]
,所以参数arg1和arg2指的是指向"a[i][0]
"的指针,我们知道,a[i][0]
是字符,就是char,所以arg1和arg2指的是char *
。我们将void*
转换为char*
,赋予a和b,调用strcmp函数对a和b进行比较。
7. qsort函数应用:整型二维数组
- 最接近原点的 K 个点
我们有一个由平面上的点组成的列表 points。需要从中找出 K 个距离原点 (0, 0) 最近的点。(这里,平面上两点之间的距离是欧几里德距离。)你可以按任何顺序返回答案。除了点坐标的顺序之外,答案确保是唯一的。
示例 1:
输入:points = [[1,3],[-2,2]], K = 1
输出:[[-2,2]]
解释: (1, 3) 和原点之间的距离为sqrt(10), (-2, 2) 和原点之间的距离为 sqrt(8), 由于 sqrt(8) < sqrt(10),(-2, 2) 离原点更近。 我们只需要距离原点最近的 K = 1 个点,所以答案就是 [[-2,2]]。
示例 2:
输入:points = [[3,3],[5,-1],[-2,4]], K = 2
输出:[[3,3],[-2,4]] (答案 [[-2,4],[3,3]] 也会被接受。)
提示:
1 <= K <= points.length <= 10000
-10000 < points[i][0] < 10000
-10000 < points[i][1] < 10000
/* qsort排序二维数组,cmp的每个元素都是一个独立的 int 数组,也就是指针 */
int cmp(const void* a, const void* b) {// 转换为对应一维数组int* arry1 = *(int**)a;int* arry2 = *(int**)b;// 获取对应arry1 的两个元素int x1 = *arry1;int y1 = *(arry1 + 1);int x2 = *arry2;int y2 = *(arry2+1);return (x1*x1 + y1*y1) - (x2*x2 + y2*y2);
}int** kClosest(int** points, int pointsSize, int* pointsColSize, int K, int* returnSize, int** returnColumnSizes){if(points==NULL || pointsSize==0 || K==0) return NULL;qsort(points, pointsSize, sizeof(int)*pointsColSize[0], cmp);/* 这里注意 qsort 的传参,使用不当会报错Line 11: Char 11: runtime error: load of misaligned address 0x602000000032 for type 'int *', which requires 8 byte alignment (solution.c) 0x602000000032: note: pointer points here*/// 指定return输出的二维数组是包含有几个一维数组*returnSize = pointsSize > K ? K : pointsSize;*returnColumnSizes = (int*)malloc(sizeof(int*)*(*returnSize));// 指定每个一维数组的 col for(int i = 0; i< (*returnSize); i++) {(*returnColumnSizes)[i] = 2;}return points;
}
养成习惯,先赞后看!如果觉得写的不错,欢迎关注,点赞,在看,转发,谢谢!
qsort函数使用方法总结(详细全面+代码)相关推荐
- 《C语言初阶进阶完整教程》- 已完结 - qsort函数使用方法+(数组,结构体,手动实现函数)
目录 前言 一.解释qsort函数 1.函数原型 2.深度解析comper比较函数 二.函数使用 1.int 2.结构体 三.手动实现函数 2.核心代码(两段) 四.升级使用方法 前言 提示:此文章可 ...
- C语言qsort函数使用方法大全
文章目录 一.qsort函数简介 二.qsort函数常用实例 1.比较整型数组 2.比较char数组 3.比较double数组 4.比较字符串 4.1按首字母排序 4.2按长度排序 4,3按字典顺序 ...
- java switch enum对象_Java枚举类(enum)5种常见用法和3种内部方法,详细附代码
文章目录 Java枚举类(enum)重点用法和内部方法,附代码 一.Java 枚举类(enum) 详解5种常见的用法 1.常量 2.支持switch 3.向枚举中添加新方法 4.覆盖枚举的方法 5.实 ...
- Go语言教程第三集 集合、函数和方法
04 集合类型:如何正确使用 array.lice 和 map? 上节课的思考题是练习使用 for 循环中的 continue,通过上节课的学习,你已经了解 continue 是跳出本次循环的意思,现 ...
- C语言 快速排序——qsort函数详解
我们在使用冒泡排序法做题的时候,经常会遇到运算次数过多程序超时的情况,而且冒泡排序法只能对整形数组进行排序. 为了解决这些问题!就使用qsort函数吧! 目录 一.qsort函数使用方法 二.qsor ...
- ML之sklearn:sklearn的make_pipeline函数、RobustScaler函数、KFold函数、cross_val_score函数的代码解释、使用方法之详细攻略
ML之sklearn:sklearn的make_pipeline函数.RobustScaler函数.KFold函数.cross_val_score函数的代码解释.使用方法之详细攻略 目录 sklear ...
- ML之sklearn:sklearn的RobustScaler函数、KFold函数、cross_val_score函数的代码解释、使用方法之详细攻略
ML之sklearn:sklearn的RobustScaler函数.KFold函数.cross_val_score函数的代码解释.使用方法之详细攻略 目录 sklearn的RobustScaler函数 ...
- Python之pandas:pandas的get_dummies函数简介(将分类变量转为哑变量)及其使用方法之详细攻略
Python之pandas:pandas的get_dummies函数简介(将分类变量转为哑变量)及其使用方法之详细攻略 目录 pandas的get_dummies函数简介 pandas.get_dum ...
- sklearn:sklearn.GridSearchCV函数的简介、使用方法之详细攻略
sklearn:sklearn.GridSearchCVl函数的简介.使用方法之详细攻略 目录 sklearn.GridSearchCV函数的简介 1.参数说明 2.功能代码 sklearn.Grid ...
最新文章
- spring事物配置,声明式事务管理和基于@Transactional注解的使用
- 把虚拟系统接入网络 虚拟系统工作模式
- davinci项目服务器无法,集成就能降成本!GS集成DaVinci Resolve项目服务器
- JavaScript三种创建构造函数的方式
- 一文看懂计算机神经网络与梯度下降
- 混合代码块 Markdown Leedcde
- 京东投票项目开发笔记
- Python一键生成国庆出行攻略,助你出门远游嗨不停!
- win32以动态链接库导出类及其成员变量
- 2018年双十一:计算机品类纸质书籍销量冠军
- ubuntu eclipseJDK
- niva mysql_Nivacat for mysql是一种第三方提供的()_学小易找答案
- Setup Factory 9 Trial使用
- 大学生购买笔记本电脑防坑指南
- 【C++】模板进阶 — 模板特化
- android中一些特殊字符(如:←↑→↓等箭头符号)的Unicode码值
- Zookeeper的Centos集群搭建
- 公务员考试要求及流程梳理
- JS流程控制语句 反反复复(while循环) 和for循环有相同功能的还有while循环, while循环重复执行一段代码,直到某个条件不再满足。...
- 计算机编程职称论文,自动化工程师职称论文
热门文章
- MYSQL学习与数据库综合实验(七)——参照性完整实验
- CycleGAN和Conditional GAN(cGAN)
- What‘s the difference between Architectural Patterns and Architectural Styles?
- css 清空ios端_CSS 修改 IOS 默认按钮样式
- 字符与数字的转换 C++
- security面试_17道APP测试面试题分享带参考答案
- 【网络丢包故障处理方案,快快点击收藏吧】
- 【电脑没声音怎么办】
- 使用window.print()后,未关闭打印页面,原网页不能操作
- 一虾两吃,500克的虾吃出600克的质感