zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    2015.2.27 UltraEdit中显示XML结构
    2015.1.31 DataGridView自动滚动到某行
    2015.1.15 利用函数实现将一行记录拆分成多行记录 (多年想要的效果)
    2015.1.15 利用Oracle函数返回表结果 重大技术进步!
    2015.1.15 利用Oracle函数插入表结构 Bulk collect into 不用循环,简洁高效
    2015.1.8 Left join 左连接
    2015.1.10 解决DataGridView SelectionChanged事件自动触发问题
    delphi 遍历窗口
    delphi 访问 protected 属性 哈哈
    clientdataset 读取excel 如果excel 文件不存在的时候 相应的gird 会不显示数据, 鼠标掠过 gird 格子 才会显示数据。 这是一个bug 哈哈
  • 原文地址:https://www.cnblogs.com/huashanqingzhu/p/12342092.html
Copyright © 2011-2022 走看看