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(voidbase,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]=;
160         printf("%s
",strArr[i]);
161     }
162     printf("
");    
163     //-------------------------------------------------------
164     qsort(strArr,n,sizeof(strArr[0]),cmp5);//字符串数组从小到大排序 
165     for(i=0;i<n;i++)
166         printf("%s
",strArr[i]);
167     printf("


");
168     //-------------------------------------------------------
169     
170     
171     
172     //-------------------------------------------------------
173     n=10;
174     for(i=0;i<n;i++)//生成stu结构体类型的随机数据
175     {
176         stuArr[i].No=1000+i;
177         stuArr[i].yuWen=getRandomInt(90,150);
178         stuArr[i].shuXue=getRandomInt(90,150);
179         stuArr[i].yingYu=getRandomInt(90,150);
180         stuArr[i].zongFen=stuArr[i].yuWen+stuArr[i].shuXue+stuArr[i].yingYu;
181         printf("%d %3d %3d %3d %3d
",stuArr[i].No,stuArr[i].yuWen,stuArr[i].shuXue,stuArr[i].yingYu,stuArr[i].zongFen);
182     }
183     printf("
");
184     //-------------------------------------------------------
185     qsort(stuArr,n,sizeof(stuArr[0]),cmp6);//对stu类型数组排序 
186     for(i=0;i<n;i++)
187         printf("%d %3d %3d %3d %3d
",stuArr[i].No,stuArr[i].yuWen,stuArr[i].shuXue,stuArr[i].yingYu,stuArr[i].zongFen);
188     printf("


");
189     //-------------------------------------------------------
190     
191     
192     
193     //-------------------------------------------------------
194     n=10;
195     for(i=0;i<n;i++)//生成point结构体类型的随机数据 
196     {
197         pArr[i].x=getRandomInt(80,100);
198         pArr[i].y=getRandomInt(1,100);
199         printf("%2d %2d
",pArr[i].x,pArr[i].y);
200     }
201     printf("
");
202     //-------------------------------------------------------
203     qsort(pArr,n,sizeof(pArr[0]),cmp7);//对point类型数组排序 
204     for(i=0;i<n;i++)
205         printf("%2d %2d
",pArr[i].x,pArr[i].y);
206     printf("


");
207     
208     
209     
210     
211     return 0;
212 }

 

以上是关于qsort()函数详解的主要内容,如果未能解决你的问题,请参考以下文章

qsort()函数详解

C语言标准库函数qsort详解

题目1004:Median(qsort函数自定义cmp函数)

学会qsort()函数,就是如此简单,快来看看吧

qsort的理解

sort()函数详解