qsort()函数详解
Posted huashanqingzhu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了qsort()函数详解相关的知识,希望对你有一定的参考价值。
参考:
https://www.cnblogs.com/laizhenghong2012/p/8442270.html
https://www.cnblogs.com/eniac12/p/4769229.html
https://www.cnblogs.com/tsingke/p/5347672.html
排序方法有很多种:选择排序,冒泡排序,归并排序,快速排序等。快速排序是目前公认的一种比较好的排序算法。因为他速度很快,所以系统也在库里实现了这个算法,便于我们的使用。 这就是qsort函数(全称quicksort)。它是ANSI C标准中提供的,其声明在stdlib.h文件中,是根据二分法写的,其时间复杂度为n*log(n)
功能: 使用快速排序例程进行排序
头文件:stdlib.h
函数原型: void qsort(void* base,size_t num,size_t width,int(__cdecl*compare)(const void*,const void*));
参数说明:
base:待排序数组,排序之后的结果仍放在这个数组中
num: 数组中待排序元素数量
width: 各元素的占用空间大小(单位为字节)
compare: 指向函数的指针,用于确定排序的顺序(需要用户自定义一个子函数)
函数返回值:无
注意:如果两个元素的值是相同的,那么它们的前后顺序是不确定的。也就是说qsort()是一个不稳定的排序算法。
compar参数详细规则
compar参数是一个函数指针,指向一个比较两个元素的函数。比较函数的原型应该像下面这样。注意两个形参必须是const void *型。另外,因为qsort( )内部在调用compar 函数(compar实质为函数指针,这里称它所指向的函数也为compar)时,传入的实参也已经转换成const void *型,所以在compar函数内部必须将const void *型转换成待排序数组的实际类型,见下文。
int cmp(const void *p1, const void *p2);
如果cmp返回值小于0(< 0),那么p1所指向元素会被排在p2所指向元素的前面
如果cmp返回值等于0(= 0),那么p1所指向元素与p2所指向元素的顺序不确定
如果cmp返回值大于0(> 0),那么p1所指向元素会被排在p2所指向元素的后面
所以,实现cmp函数时,谨记:
如果满足某个条件时,p1元素应在p2元素前面,那么此时返回负数,比如-1;
如果满足某个条件时,p1元素应在p2元素后面,那么此时返回正数,比如1;
如果满足某个条件时,p1元素和p2元素顺序不影响,那么返回0.(这个时候一般是表示p1==p2)
使用qsort()函数的例子
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<time.h> 4 #include<string.h> 5 typedef struct 6 { 7 int No; 8 int yuWen,shuXue,yingYu,zongFen; 9 }stu; 10 typedef struct 11 { 12 int x,y; 13 }point; 14 15 //----------随机数相关子函数----------------------------- 16 int getRandomInt(int a,int b)//返回[a,b]之间一个随机整数 17 { return (rand() % (b-a+1))+ a; } 18 double getRandomDouble()//返回0~1之间随机浮点数 19 { return rand()/double(RAND_MAX); } 20 char getUpChar()//返回随机大写字母 21 { return ((char)(rand()%26+‘A‘)); } 22 char getDownChar()//返回随机小写字母 23 { return ((char)(rand()%26+‘a‘)); } 24 void InitRandom() 25 { srand((unsigned)time(0)); } 26 //------------------------------------------------------- 27 28 29 int cmp1(const void *a,const void *b)//int数组从小到大排序 30 { return *(int*)a -*(int*)b; } 31 int cmp2(const void *a,const void *b)//int数组从大到小排序 32 { return *(int*)b -*(int*)a; } 33 34 /*在对浮点或者double型的数据比较时一定要用三目运算符, 35 因为要是使用像整型那样相减的话,如果是两个很接近的数, 36 则可能返回一个很小的小数(大于-1,小于1),而cmp的返 37 回值是int型,因此会将这个小数返回0,系统认为是相等, 38 失去了本来存在的大小关系 */ 39 int cmp3(const void *a,const void *b)//double数组从小到大排序 40 { 41 //return *(double*)a -*(double*)b;//这种写法比较危险。因为无法直接判定两个浮点数相等。 42 return *(double *)a > *(double *)b ? 1 : -1; 43 } 44 45 int cmp4(const void *a,const void *b)//char数组从小到大排序 46 { return *(char*)a -*(char*)b; } 47 48 int cmp5(const void *a,const void *b)//对字符串数组排序 49 { 50 char *x=(char*)a; 51 char *y=(char*)b; 52 return strcmp(x,y); 53 } 54 55 int cmp6(const void *a,const void *b)//对stu结构体类型数组排序 56 {//优先按总分从大到小,总分相等则按学号从小到大 57 stu x=*(stu*)a; 58 stu y=*(stu*)b; 59 if(x.zongFen<y.zongFen)return 1; 60 else if(x.zongFen>y.zongFen) return -1; 61 else 62 { 63 if(x.No<y.No)return -1;//返回负数-1表示参数一应该排在参数二前面 64 else if(x.No>y.No) return 1;//返回正数1表示参数一应该排在参数二后面 65 else return 0;//返回0表示参数一和参数二相等,最终排序结果中,两者的顺序不确定。 66 } 67 } 68 int cmp7(const void *a,const void *b)//对point结构体类型数组元素排序 69 { //优先按x从小到大排序,当x相等则按y从大到小排序。 70 point *p1=(point*)a; 71 point *p2=(point*)b; 72 if(p1->x < p2->x) return -1;//返回负数-1表示参数一应该排在参数二前面 73 else if(p1->x > p2->x)return 1;//返回正数1表示参数一应该排在参数二后面 74 else 75 { 76 if(p1->y > p2->y)return -1; 77 else if(p1->y < p2->y)return 1; 78 else return 0;//返回0表示参数一和参数二相等,最终排序结果中,两者的顺序不确定。 79 } 80 } 81 82 int main() 83 { 84 int IntArr[15],IntArr2[15],IntArr3[15],i,n=15; 85 double dArr[15]; 86 char cArr[15]; 87 char strArr[100][100];//每行一个字符串 88 stu stuArr[50];//每个元素表示一个学生的数据 89 point pArr[50];//每个元素表示一个整数点的数据(x,y) 90 InitRandom(); 91 //------------------------------------------------------- 92 for(i=0;i<n;i++)//生成随机整数数组 93 { 94 IntArr3[i]=IntArr2[i]=IntArr[i]=getRandomInt(1,1000); 95 printf("%d ",IntArr[i]); 96 } 97 printf(" "); 98 //------------------------------------------------------- 99 qsort(IntArr,n,sizeof(IntArr[0]),cmp1);//int[]从小到大排序 100 for(i=0;i<n;i++) 101 printf("%d ",IntArr[i]); 102 printf(" "); 103 //------------------------------------------------------- 104 qsort(IntArr2,n,sizeof(IntArr2[0]),cmp2);//int[]从大到小排序 105 for(i=0;i<n;i++) 106 printf("%d ",IntArr2[i]); 107 printf(" "); 108 //------------------------------------------------------- 109 qsort(IntArr3+1,n-1,sizeof(IntArr3[1]),cmp2);//int[]从大到小排序,第0号元素不参与排序 110 for(i=0;i<n;i++) 111 printf("%d ",IntArr3[i]); 112 printf(" "); 113 114 115 116 //------------------------------------------------------- 117 n=10; 118 for(i=0;i<n;i++)//生成随机浮点数数组 119 { 120 dArr[i]=getRandomDouble()*1000; 121 printf("%.2lf ",dArr[i]); 122 } 123 printf(" "); 124 //------------------------------------------------------- 125 qsort(dArr,n,sizeof(dArr[0]),cmp3);//double[]从小到大排序 126 for(i=0;i<n;i++) 127 printf("%.2lf ",dArr[i]); 128 printf(" "); 129 //------------------------------------------------------- 130 131 132 133 134 //------------------------------------------------------- 135 n=15; 136 for(i=0;i<n;i++)//生成随机字符数组 137 { 138 cArr[i]=getUpChar(); 139 printf("%c ",cArr[i]); 140 } 141 printf(" "); 142 //------------------------------------------------------- 143 qsort(cArr,n,sizeof(cArr[0]),cmp4);//char[]从小到大排序 144 for(i=0;i<n;i++) 145 printf("%c ",cArr[i]); 146 printf(" "); 147 //------------------------------------------------------- 148 149 150 151 152 //------------------------------------------------------- 153 n=10; 154 for(i=0;i<n;i++)//生成随机字符串数组 155 { 156 int len=getRandomInt(5,15); 157 for(int j=0;j<len;j++) 158 strArr[i][j]=getDownChar(); 159 strArr[i][len]=‘