• 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 }
  • 相关阅读:
    非科班学习路线
    非科班秋招面试总结
    招银网络Java面经
    派分糖果
    修改CentOS7网卡名称为传统名称eth0格式
    浅谈$* 和$@的区别
    Cobbler无人值守安装
    使用kickstart + pxe 部署无人值守安装
    CentOS 7 忘记root密码解决方法
    linux系统开机流程详解
  • 原文地址:https://www.cnblogs.com/huashanqingzhu/p/12342092.html
Copyright © 2020-2023  润新知