网站首页 > 技术文章 正文
我们知道,数组排序中的“快速排序”有较高的时间效率,为此C函数库stdlib提供了此函数,并能够对整形、浮点型、字符串及至结构体中的某个关键字实现排序。我们知道,C语言是强类型语言,且没有C++的函数重载和模板机制,那怎样实现这种类型泛化的操作呢?C用void*指针和函数指针实现回调函数来达成。这也是此函数的参数看起来特别复杂的原因:
void qsort( void *base, size_t nitems, size_t size, int (*compar)(const void *, const void*))
void *base:类型为void*,相当于泛型,指向要排序的数组的第一个元素的指针。
nitems:数组中元素的个数,在数组指针中无法内含元素个数,需要另外的参数提供。
size:因为数据指针提供的是void*类型,需要另外的参数来提供数组中每个元素的大小,以字节为单位。
int compar(const void *p1, const void *p2);
compar是一个函数指针,注意函数参数的类型是void*,可以是各种基本类型、字符串、结构体的某个关键字,用来比较两个元素的函数,即函数指针(回调函数)
如果compar返回值小于0(< 0),那么p1所指向元素会被排在p2所指向元素的前面;
如果compar返回值等于0(= 0),那么p1所指向元素与p2所指向元素的顺序不确定;
如果compar返回值大于0(> 0),那么p1所指向元素会被排在p2所指向元素的后面。
实例:
#include <stdio.h> #include <stdlib.h> #define NUM 40 void fillarray(double ar[], int n); void showarray(const double ar[], int n); int mycomp(const void * p1, const void * p2); int main(void) { double vals[NUM]; fillarray(vals, NUM); puts("Random list:"); showarray(vals, NUM); qsort(vals, NUM, sizeof(double), mycomp); puts("\nSorted list:"); showarray(vals, NUM); system("pause"); return 0; } void fillarray(double ar[], int n) { int index; for( index = 0; index < n; index++) ar[index] = (double)rand()/((double) rand() + 0.1); } void showarray(const double ar[], int n) { int index; for( index = 0; index < n; index++) { printf("%9.4f ", ar[index]); if (index % 6 == 5) putchar('\n'); } if (index % 6 != 0) putchar('\n'); } /* sort by increasing value */ int mycomp(const void * p1, const void * p2) { /* need to use pointers to double to access values */ const double * a1 = (const double *) p1; const double * a2 = (const double *) p2; return *(int*)a-*(int*)b; if (*a1 < *a2) return -1; else if (*a1 == *a2) return 0; else return 1; }
各种类型回调函数的写法
1 整形
int comp(const void*a,const void*b) { return *(int*)a-*(int*)b;//由小到大排序 //return *(int *)b - *(int *)a; 为由大到小排序。 }
2 浮点型
int mycomp(const void * p1, const void * p2) { const double * a1 = (const double *) p1; const double * a2 = (const double *) p2; return *(int*)a-*(int*)b; if (*a1 < *a2) return -1; else if (*a1 == *a2) return 0; else return 1; }
3 对一个整型二维数组按行的第一个元素进行排序,要求整行一起移动交换。
qsort(a,1000,sizeof(int)*2,comp);//两列 int comp(const void*a,const void*b) { return((int*)a)[0]-((int*)b)[0]; }
4 字符串
int Comp(const void*p1,const void*p2) { return strcmp((char*)p2,(char*)p1); }
5 按结构体中某个关键字排序
structNode { double data; int other; }s[100]; int Comp(constvoid*p1,constvoid*p2) { return(*(Node*)p2).data>(*(Node*)p1).data?1:-1; }
5 按结构体中多个关键字排序(对结构体多级排序)[以二级为例]
struct Node { int x; int y; }s[100]; //按照x从小到大排序,当x相等时按y从大到小排序 int Comp(const void*p1,const void*p2) { struct Node*c=(Node*)p1; struct Node*d=(Node*)p2; if(c->x!=d->x) returnc->x-d->x; else return d->y-c->y; }
6 对结构体中字符串进行排序
struct Node { int data; char str[100]; }s[100]; //按照结构体中字符串str的字典序排序 int Comp(const void*p1,const void*p2) { return strcmp((*(Node*)p1).str,(*(Node*)p2).str); } qsort(s,100,sizeof(s[0]),Comp);
-End-
猜你喜欢
- 2024-10-26 C语言、嵌入式项目中一些常用知识及技巧第一弹
- 2024-10-26 C语言编程:最常见 7 道C语言面试题,还是有不少人弄不明白?
- 2024-10-26 初识C语言:简介、环境搭建、第一个HelloWorld
- 2024-10-26 C|volatile关键字使用细节及适用场合
- 2024-10-26 C语言干货:函数知识详解(变量的作用域,全局变量,静态变量)
- 2024-10-26 小白入门C语言20问20答2(新手c语言)
- 2024-10-26 C语言的简单了解及学习2(c语言的入门知识)
- 2024-10-26 C 语言基本语法(c语言的基础语法)
- 2024-10-26 C语言数据怎么描述?最全面解析,C语言基础教学档案!编号零零五
- 2024-10-26 C语言void关键字的高级玩法,6个样例代码告诉你
- 02-21走进git时代, 你该怎么玩?_gits
- 02-21GitHub是什么?它可不仅仅是云中的Git版本控制器
- 02-21Git常用操作总结_git基本用法
- 02-21为什么互联网巨头使用Git而放弃SVN?(含核心命令与原理)
- 02-21Git 高级用法,喜欢就拿去用_git基本用法
- 02-21Git常用命令和Git团队使用规范指南
- 02-21总结几个常用的Git命令的使用方法
- 02-21Git工作原理和常用指令_git原理详解
- 最近发表
- 标签列表
-
- cmd/c (57)
- c++中::是什么意思 (57)
- sqlset (59)
- ps可以打开pdf格式吗 (58)
- phprequire_once (61)
- localstorage.removeitem (74)
- routermode (59)
- vector线程安全吗 (70)
- & (66)
- java (73)
- org.redisson (64)
- log.warn (60)
- cannotinstantiatethetype (62)
- js数组插入 (83)
- resttemplateokhttp (59)
- gormwherein (64)
- linux删除一个文件夹 (65)
- mac安装java (72)
- reader.onload (61)
- outofmemoryerror是什么意思 (64)
- flask文件上传 (63)
- eacces (67)
- 查看mysql是否启动 (70)
- java是值传递还是引用传递 (58)
- 无效的列索引 (74)