码迷,mamicode.com
首页 > 其他好文 > 详细

快排函数qsort(s,n,sizeof(s[0]),cmp) 与 int cmp(const void *a, const void *b) 的具体用法以及注意事项

时间:2021-01-18 11:19:28      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:can   string   ++   数组   个人   --   for   比较   i+1   


             ** 关于快排函数的一些说明 ** 
qsort,包含在stdlib.h头文件里,函数一共四个参数,没返回值.一个典型的qsort的写法如下 
qsort(s,n,sizeof(s[0]),cmp); 
第一个参数是参与排序的数组名(或者也可以理解成开始排序的地址,可以写&s[i] 
这样的表达式);

第二个参数是参与排序的元素个数; 第三个三数是 

单个元素的大小,推荐使用sizeof(s[0])这样的表达式) ;

第四个参数就是 比较函数cmp

我们来讨论cmp这个比较函数
int cmp(const void *a,const void *b); (写cmp只是因为许多例子都是这样写,命名成别的也是可以的)
返回值必须是int,两个参数的类型必须都是const void *类型(变量名根据个人喜好)
假设是对int排序的话,如果是升序,那么就是如果a比b大,则返回一个正值,小则负值,相等返回 
0,其他的依次类推, 根据具体情况具体选用相关形式,后面有代码作为示例
注意:在函数体内要对a,b进行强制类型转换后才能得到正确的返回值,不同的类型有不同的处理 
方法.在后面会具体给出相关代码作为示例


                                 ** 关于快排的一些小问题 ** 
1.不稳定性。快排是不稳定的,这个不稳定一个表现在其使用的时间是不确定的,最好情况(O(n))和最 
坏情况(O(n^2))差距太大,我们一般说的O(nlog(n))都是指的是其平均时间. 
2.快排是不稳定的,这个不稳定表现在如果相同的比较元素,可能顺序不一样,假设我们有 
这样一个序列为3,3,3,但是这三个3是有区别的,我们标记为3a,3b,3c,快排后的结果不一定 
就是3a,3b,3c这样的排列顺序,所以在某些特定场合我们要用结构体来使其稳定,结构体可以作为一个稳定的整体在调用部分的过程中达到稳定效果

(No.6就是说明这个问题的) 
3.快排的比较函数的两个参数必须都是const void *的。(再次说明:定义函数名为cmp以及两个参数为a,b仅仅是我的个人习惯,并非函数库内写好的定义。)

推荐在cmp里面重新定义两个指针来强制类型转换, 
特别是在对结构体进行排序的时候,必须进行该操作以增加稳定性 
4.快排qsort的第三个参数,那个sizeof,推荐是使用sizeof(s[0])进行操作,特别是对结构体, 因为使用自己定义的2*sizeof(int)可能会出现问题
5.如果要对数组进行部分排序,比如对一个s[n]的数组排列其从s[i]开始的m个元素,只需要 
在第一个和第二个参数上进行一些修改:qsort(&s[i],m,sizeof(s[i]),cmp); 
这里进行简单的说明:因为正常情况下的数组可以使用s就可以,这仅仅是因为是数组的首地址可以使用数组名称简写代替,若是用标准的形式应该是&s[0],所以单从s[i]开始的排序自然要使用该位置的地址
                                   
                       ** 举例说明 ** 
(该举例均来自网络上的其他博主,大家自行参考,仅推荐学习在处理不同情况下的cmp转化等操作,代码的准确性有待考证)
No.1.手工实现QuickSort 
#include <stdio.h> 
int a[100],n,temp; 
void QuickSort(int h,int t) 

if(h>=t) return; 
int mid=(h+t)/2,i=h,j=t,x; 
x=a[mid]; 
while(1) 

while(a[i]<x) i++; 
while(a[j]>x) j--; 
if(i>=j) break; 
temp=a[i]; 
a[i]=a[j]; 
a[j]=temp; 

a[mid]=a[j]; 
a[j]=x; 
QuickSort(h,j-1); 
QuickSort(j+1,t); 
return; 

int main() 

int i; 
scanf("%d",&n); 
for(i=0;i<n;i++) scanf("%d",&a[i]); 
QuickSort(0,n-1); 
for(i=0;i<n;i++) printf("%d ",a[i]); 
return(0); 

No.2.最常见的,对int数组排序 
#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
int s[10000],n,i; 
int cmp(const void *a, const void *b) 

return(*(int *)a-*(int *)b); 

int main() 

scanf("%d",&n); 
for(i=0;i<n;i++) scanf("%d",&s[i]); 

qsort(s,n,sizeof(s[0]),cmp); 

for(i=0;i<n;i++) printf("%d ",s[i]); 

return(0); 

No.3.对double型数组排序,原理同int 
这里做个注释,本来是因为要判断如果a==b返回0的,但是严格来说,两个double数是不可能相等的,只能说fabs(a-b)<1e-20之类的这样来判断,所以这里只返回了1和-1 
#include <stdio.h> 
#include <stdlib.h> 
double s[1000]; 
int i,n; 
int cmp(const void * a, const void * b) 

return((*(double*)a-*(double*)b>0)?1:-1); 

int main() 

scanf("%d",&n); 
for(i=0;i<n;i++) scanf("%lf",&s[i]); 

qsort(s,n,sizeof(s[0]),cmp); 

for(i=0;i<n;i++) printf("%lf ",s[i]); 

return(0); 

No.4.对一个字符数组排序.原理同int 
#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
char s[10000],i,n; 
int cmp(const void *a,const void *b) 

return(*(char *)a-*(char *)b); 

int main() 

scanf("%s",s); 
n=strlen(s); 
qsort(s,n,sizeof(s[0]),cmp); 

printf("%s",s); 
return(0); 

No.5.对结构体排序 
注意:很多时候我们都会对结构体排序,一般这个时候都在cmp函数里面先强制转换了类型 
不要尝试在return里面转,这样不会出错,可能是编译器的差别,这里特别容易报错还找不到原因.
这里请注意double返回0的问题 ,参考上面的例子理解
#include <stdio.h> 
#include <stdlib.h> 
struct node 

double date1; 
int no; 
} s[100]; 
int i,n; 
int cmp(const void *a,const void *b) 

struct node *aa=(node *)a; 
struct node *bb=(node *)b; 
return(((aa->date1)>(bb->date1))?1:-1); 

int main() 

scanf("%d",&n); 
for(i=0;i<n;i++) 

s[i].no=i+1; 
scanf("%lf",&s[i].date1); 

qsort(s,n,sizeof(s[0]),cmp); 

for(i=0;i<n;i++) printf("%d %lf\n",s[i].no,s[i].date1); 

return(0); 

No.6.对结构体排序.加入no来使其稳定(即data值相等的情况下按原来的顺序排) ,仅仅需要在结构体内部加入no变量作为稳定器的作用
#include <stdio.h> 
#include <stdlib.h> 
struct node 

double date1; 
int no; 
} s[100]; 
int i,n; 
int cmp(const void *a,const void *b) 

struct node *aa=(node *)a; 
struct node *bb=(node *)b; 
if(aa->date1!=bb->date1) 
return(((aa->date1)>(bb->date1))?1:-1); 
else 
return((aa->no)-(bb->no)); 

int main() 

scanf("%d",&n); 
for(i=0;i<n;i++) 

s[i].no=i+1; 
scanf("%lf",&s[i].date1); 

qsort(s,n,sizeof(s[0]),cmp); 
for(i=0;i<n;i++) printf("%d %lf\n",s[i].no,s[i].date1); 
return(0); 

No.7.对字符串数组的排序(char s[][]类型的二重数组) 
#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
char s[100][100]; 
int i,n; 
int cmp(const void *a,const void *b) 

return(strcmp((char*)a,(char*)b)); 

int main() 

scanf("%d",&n); 
for(i=0;i<n;i++) scanf("%s",s[i]); 

qsort(s,n,sizeof(s[0]),cmp); 

for(i=0;i<n;i++) printf("%s\n",s[i]); 

return(0); 

No.8.对字符串数组排序(char *s[]型) 
#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
char *s[100]; 
int i,n; 
int cmp(const void *a,const void *b) 

return(strcmp(*(char**)a,*(char**)b)); 

int main() 

scanf("%d",&n); 
for(i=0;i<n;i++) 

s[i]=(char*)malloc(sizeof(char*)); 
scanf("%s",s[i]); 

qsort(s,n,sizeof(s[0]),cmp); 
for(i=0;i<n;i++) printf("%s\n",s[i]); 
return(0); 

快排函数qsort(s,n,sizeof(s[0]),cmp) 与 int cmp(const void *a, const void *b) 的具体用法以及注意事项

标签:can   string   ++   数组   个人   --   for   比较   i+1   

原文地址:https://www.cnblogs.com/2811358062qq/p/14288451.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!