• C中的qsort函数和C++中的sort函数的理解与使用


    一、qsort()函数

    原型:_CRTIMP void __cdecl qsort (void*, size_t, size_t,int (*)(const void*, const void*));

    参数解释:1、待排序数组首地址;2、数组中待排序元素数量;3、各元素的占用空间的大小;4、指向函数的指针,用于确定排序的顺序。

    说明:qsort函数是ANSI C标准中提供的,其声明在stdlib.h文件中,是根据二分法写的,时间复杂度为O(n*logn)。

    qsort要求提供比较函数用来确定排序的顺序(升序、降序),比较函数使得qsort通用性更好,可以对数组、字符串、结构体数进行排序。如int cmp(const void *a, const void *b)中有两个元素作为参数(参数的格式不能变的。)返回一个int值,如果比较函数返回大于0,qsort就认为a > b,返回小于0,qsort就认为a < b。

    1、qsort中几种常见的cmp函数

    1.1、对int类型数组排序

    int num[100];
    int cmp(const void *a, const void *b)
    {
        return *(int *)a - *(int *)b;
    }
    
    qsort(num, 100, sizeof(int), cmp);

    1.2、对char类型数组排序

    char num[100];
    int cmp(const void *a, const void *b)
    {
        return *(char *)a - *(char *)b;
    }
    
    qsort(num, 100, sizeof(char), cmp);

    1.3、对double类型数组排序

    double num[100];
    int cmp(const void *a, const void *b)
    {
        return *(double *)a > *(double *)b;
    }
    
    qsort(num, 100, sizeof(double), cmp);

    1.4、对结构体数组一级排序

    struct In
    {
        double data;
        int other;
    }s[100]
    //按照data的值从小到大将结构体排序,关于结构体内的排序关键数据data的类型可以很多种,参考上面的例子写 
    int cmp( const void *a ,const void *b)
    {
        return (*(In *)a)->data > (*(In *)b)->data ? 1 : -1;
    }
    
    qsort(s,100,sizeof(In),cmp); 

    1.5、对结构体数组二级排序

    struct In
    {
        int x;
        int y;
    }s[100];
    //按照x从小到大排序,当x相等时按照y从大到小排序 
    int cmp( const void *a , const void *b )
    {
        struct In *c = (In *)a;
        struct In *d = (In *)b;
        if(c->x != d->x) 
            return c->x - d->x;
        else
            return d->y - c->y;
    }
    
    qsort(s,100,sizeof(In),cmp);       

    1.6、对字符串进行排序

    struct In
    
    {
        int data;
        char str[100];
    }s[100];
    //按照结构体中字符串str的字典顺序排序 
    int cmp ( const void *a , const void *b )
    {
        return strcmp( (*(In *)a)->str , (*(In *)b)->str );
    }
    qsort(s,100,sizeof(In),cmp); 

    1.7、计算几何中求凸包的cmp

    int cmp(const void *a,const void *b) //重点cmp函数,把除了1点外的所有点,旋转角度排序 
    {
        struct point *c=(point *)a;
        struct point *d=(point *)b;
        if( calc(*c,*d,p[1]) < 0) 
        return 1; else if( !calc(*c,*d,p[1]) && dis(c->x,c->y,p[1].x,p[1].y) < dis(d->x,d->y,p[1].x,p[1].y)) //如果在一条直线上,则把远的放在前面   return 1; else
        return -1; }

    2、拓展知识点

    one、为啥子使用qsort函数要指定排序元素的大小?

    ans:这是个脑残的问题,给个脑残的答案吧。因为qsort需要根据元素的大小来进行排序。

    two、 所使用的比较函式接受的是 const void* 类型?

    ans:因为考虑到qsort的通用性,这样可以对数组,结构体数组等类型进行排序了。

    二、sort()函数

    函数名功能描述
    sort 对给定区间所有元素进行排序
    stable_sort 对给定区间所有元素进行稳定排序
    partial_sort 对给定区间所有元素部分排序
    partial_sort_copy 对给定区间复制并排序
    nth_element 找出给定区间的某个位置对应的元素
    is_sorted 判断一个区间是否已经排好序
    partition 使得符合某个条件的元素放在前面
    stable_partition 相对稳定的使得符合某个条件的元素放在前面

    要使用上述函数必须加上头文件algorithm。

    1、sort(begin,end)

    小例子

    #include<algorithm>
    
    int _tmain(int argc, _TCHAR* argv[])
    {
         int a[20]={2,4,1,23,5,76,0,43,24,65},i;
         for(i=0;i<20;i++)
              cout<<a[i]<<endl;
         sort(a,a+20);
         for(i=0;i<20;i++)
             cout<<a[i]<<endl;
         return 0;
    }    

    输出结果是把数组a按升序排序,也就是sort函数的排序默认是升序的。

    如何使用sort函数降序排序,ok!就像qsort中一样,我们需要自定义一个比较函数cmp(返回值为bool类型)。

    2、重载的sort函数-带比较函数的sort(begin,end,cmp)

    定义比较函数的方法

    2.1、常用方法

    下面的比较函数可以实现降序排序:

    bool cmp(int a,int b)
    {
        return a>b;      
    }

    2.2、使用枚举类型enum来定义升序或者降序排序。

    //ASC升序,DESC降序
    enum Cmp{ASC,DESC};

    2.3 定义一个比较类,来描述排序的顺序。

    class compare
    {
          private:
                Cmp comp;
          public:
                compare(Cmp c):comp(c) {};
          bool operator () (int num1,int num2) 
             {
                switch(comp)
                  {
                     case ASC:
                            return num1<num2;
                     case DESC:
                            return num1>num2;
                  }
              }
    };

    测试一下:

    int main()
    {
         int a[20]={2,4,1,23,5,76,0,43,24,65},i;
         for(i=0;i<20;i++)
             cout<<a[i]<<endl;
         sort(a,a+20,compare(DESC));
         for(i=0;i<20;i++)
             cout<<a[i]<<endl;
         return 0;
    }

    了解一下即可,因为比较麻烦,根据实际情况使用。

    2.4、使用functional头文件中的比较对象。

    functional提供了一堆基于模板的比较函数对象。equal_to<Type>、not_equal_to<Type>、greater<Type>、greater_equal<Type>、less<Type>、less_equal<Type>。对于这些比较对象,我们可以望文生义就知道它们的意思了。

    for example:

    sort(begin,end,less<data-type>();//升序
    
    sort(begin,end,greater<data-type>();//降序

    接着上面的例子,使用一下比较对象

    int _tmain(int argc, _TCHAR* argv[])
    {
          int a[20]={2,4,1,23,5,76,0,43,24,65},i;
          for(i=0;i<20;i++)
              cout<<a[i]<<endl;
          sort(a,a+20,greater<int>());
          for(i=0;i<20;i++)
              cout<<a[i]<<endl;
          return 0;
    }

    三、qsort函数和sort函数的PK。

    1、cmp函数不同

    返回值类型不同,qsort函数的cmp返回值类型为int,sort函数的cmp返回值为bool。

    参数不同,sort函数的cmp可以直接是参与比较的引用类型,而qsort是严格的空指针类型。

    比较表达式不同,qsort中的cmp使用的是“-”号,而sort中的cmp使用的是“>”。

    2、性能的区别

    sort函数是c++中标准模板库的的函数,在qsort()上已经进行了优化,根据情况的不同可以采用不同的算法,所以较快。在同样的元素较多和同样的比较条件下,sort()的执行速度都比qsort()要快。另外,sort()是类属函数,可以用于比较任何容器,任何元素,任何条件。

  • 相关阅读:
    centos7.2安装配置
    CentOS系统操作mysql的常用命令
    MySQL5.7安装与配置(YUM)
    排序的空间复杂度和尾递归小记
    常见内排序实现汇总(含部分优化实现,基于链表的实现),以及性能比较
    [ASP.NET]从ASP.NET Postback机制,到POST/GET方法
    内存管理笔记(分页,分段,逻辑地址,物理地址与地址转换方式)
    [EXT JS]"hasMany" association on ExtJS 4.1.1a
    使用nodejs抓取博客园内容---Promise模块探索
    NodeJs + mongodb模块demo
  • 原文地址:https://www.cnblogs.com/tgycoder/p/5016846.html
Copyright © 2020-2023  润新知