C语言qsort解析

第一篇

qsort(基本快速排序的方法,每次把数组分成两部分和中间的一个划分值,而对于有多个重复值的数组来说,基本快速排序的效率较低,且不稳定)。集成在C语言库函数里面的的qsort函数,使用 三 路划分的方法解决排序这个问题。所谓三路划分,是指把数组划分成小于划分值,等于划分值和大于划分值的三个部分。

具体介绍:-^^

voidqsort( void *base, size_t num, size_t width, int (__cdecl *compare )

intcompare (const void *elem1, const void *elem2 ) );

qsort(即,quicksort)主要根据你给的比较条件给一个快速排序,主要是通过指针移动实现排序功能。排序之后的结果仍然放在原来数组中。

参数意义如下:

第一个参数 base 是 需要排序的目标数组名(或者也可以理解成开始排序的地址,因为可以写&s[i]这样的表达式)

第二个参数 num 是 参与排序的目标数组元素个数

第三个参数 width 是单个元素的大小(或者目标数组中每一个元素长度),推荐使用sizeof(s[0])这样的表达式

第四个参数 compare 就是让很多人觉得非常困惑的比较函数啦。

扫描二维码关注公众号,回复: 4883274 查看本文章

我们来简单讨论compare这个比较函数(写成compare是我的个人喜好,你可以随便写成什么,比如 cmp 什么的,在后面我会一直用cmp做解释)。

典型的compare的定义是int compare(const void *a,constvoid *b);

返回值必须是int,两个参数的类型必须都是const void *,那个a,b是随便写的,个人喜好。假设是对int排序的话,如果是升序,那么就是如果a比b大返回一个正值,小则负值,相等返回0,其他的依次类推,后面有例子来说明对不同的类型如何进行排序。

qsort的使用方法:

一、对int类型数组排序

int num[100];

int cmp ( const void *a , const void *b )

{

  return *(int *)a - *(int *)b;  //升序排序

//return*(int *)b - *(int *)a; //降序排序

/*可见:参数列表是两个空指针,现在他要去指向你的数组元素。所以转型为你当前的类型,然后取值。

        升序排列时,若第一个参数指针指向的“值”大于第二个参数指针指向的“值”,则返回正;若第一个参数指针指向的“值”等于第二个参数指针指向的“值”,则返回零;若第一个参数指针指向的“值”小于第二个参数指针指向的“值”,则返回负。

        降序排列时,则刚好相反。

*/

}

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

示例完整函数(已在 VC6.0上运行通过):

#include<stdio.h>

#include<string.h>

#include<stdlib.h>

int s[10000],n,i;

int cmp(const void *a,const void *b)

{

return(*(int*)b-*(int *)a);  //实现的是升序排序

}

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);

}

二、对char类型数组排序(同int类型)

char word[100];

int cmp( const void *a , const void *b )

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

}

qsort(word,100,sizeof(word[0]),cmp);

//附,可能getchar(); 会派上用场

三、对double类型数组排序(特别要注意)

double in[100];

int cmp( const void *a , const void *b )

{

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

//返回值的问题,显然cmp返回的是一个整型,所以避免double返回小数而被丢失,用一个判断返回值。

}

qsort(in,100,sizeof(in[0]),cmp);

//附:排序结果的输出,一般建议用 “ %g ” 格式

四、对结构体一级排序

struct In

{

double data;

int other;

}s[100]


 


int cmp( const void *a ,const void *b)

{

return(*(In *)a).data > (*(In *)b).data ? 1 : -1;

//或者你可以将这上面1条语句改成下面这3条语句

//structIn *aa = (In *)a;

//structIn *bb = (In *)b;

//returnaa->data > bb->data ? 1 : -1;

}

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

五、对结构体二级排序

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(s[0]),cmp);

六、对字符串进行排序

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(s[0]),cmp);

 

注意!qsort 中的 cmp 得自己写 。

再说说 sort (常用于 C++ )

sort使用时得注明:using namespace std; 或直接打 std::sort() 还得加上 #include 头文件

例:

#include<iostream>

#include<algorithm>

usingnamespace std;

 

int main()

{

     int a[20];

   for(int i=0;i<20;++i)

              cin>>a[i];

 

     sort(a,a+20);             //范围,很明显这里是a+20 注意,这是必要的,如果是a+19

       for(i=0;i<20;i++)        //最后一个值a[19]就不会参与排序。

              cout<<a[i]<<endl;

     return0;

}

std::sort是一个改进版的qsort. std::sort函数优于qsort的一些特点:对大数组采取9项取样,更完全的三路划分算法,更细致的对不同数组大小采用不同方法排序。

最后,我们来说说sort、qsort的区别:

sort是qsort的升级版,如果能用sort尽量用sort,使用也比较简单,不像qsort还得自己去写 cmp 函数,只要注明 使用的库函数就可以使用,参数只有两个(如果是普通用法)头指针和尾指针;

默认sort排序后是升序,如果想让他降序排列,可以使用自己编的cmp函数

#include<iostream>

#include<algorithm>

usingnamespace std;

int cmp(int a,int b)

{

  if(a<b)

  return 1; //升序排列,如果改为 a >b,则为降序,要注意sort()中cmp()的返值只有1和0,不像qsort中存在-1!!!!

  else

  return 0;

}

 

int main(){

       int i;

 int a[20];

 for(int i=0;i<5;++i)

  cin>>a[i];

sort(a,a+5,cmp);          //范围,很明显这里是a+5 注意,这是必要的,如果是a+4最后一个值a[4]就不会参与排序。

for(i=0;i<5;i++)      

cout<<a[i]<<endl;

       system("pause");

 return 0;

}

对二维数组的排序:

#include<iostream>

#include<algorithm>

#include<ctime>

usingnamespace std;

 

bool cmp(int *p,int *q)

{

       if(p[0]==q[0])

       {

           if(p[1]==q[1])

           {

               return p[2]<q[2];

           }

           else return p[1]<q[1];

       }

       else return p[0]<q[0];

}

int main()

{

       srand(time(0));

       int i;

       int **a=new int*[1000];

       for(i=0;i<1000;++i)

       {

           a[i]=newint[3];

           a[i][0]=rand()%1000;

           a[i][1]=rand()%1000;

           a[i][2]=rand()%1000;

           //printf("%d\t%d\t%d\n",a[i][0],a[i][1],a[i][2]);

       }

       sort(a,a+1000,cmp);

       /*cout<<"Aftersort"<<endl;

       for(i=0;i<1000;++i)

       {

           printf("%d\t%d\t%d\n",a[i][0],a[i][1],a[i][2]);

       }*/

       return 0;

}

第二篇

C语言标准库函数 qsort详解
qsort包含在<stdlib.h>头文件中,此函数根据你给的比较条件进行快速排序,通过指针移动实现排序。排序之后的结果仍然放在原数组中。使用qsort函数必须自己写一个比较函数。

函数原型:

void qsort ( void * base, size_tnum, size_t size, int ( * comparator ) ( const void *, const void * ) );

指向任意数据类型的指针都可以转换为void*类型

用法以及参数说明:
Sortsthe num elements of the array pointed by base, each element size bytes long,using the comparator function to determine the order.

   Thesorting algorithm used by this function compares pairs of values by calling thespecified comparator function with two pointers to elements of the array.

   Thefunction does not return any value, but modifies the content of the arraypointed by base reordering its elements to the newly sorted order.

   basePointer to the first element of the array to be sorted.(数组起始地址)

   numNumber of elements in the array pointed by base.(数组元素个数)

   sizeSize in bytes of each element in the array.(每一个元素的大小)

   comparatorFunction that compares two elements.(函数指针,指向比较函数)

1、The function must accept two parameters that are pointers to elements,type-casted as void*. These parameters should be cast back to some data typeand be compared.

2、The return value of this function should represent whether elem1 isconsidered less than, equal to, or greater than elem2 by returning,respectively, a negative value, zero or a positive value.

Return Value none (无返回值)

   给你们的C++帮助文档上面的语法及定义是:

语法:

#include <stdlib.h>

void qsort( void *buf, size_t num, size_t size, int (*compare)(const void *, const void *) );

功能: 对buf 指向的数据(包含num 项,每项的大小为size)进行快速排序。如果函数compare 的第一个参数小于第二个参数,返回负值;如果等于返回零值;如果大于返回正值。函数对buf 指向的数据按升序排序。

关键比较函数

一、对int类型数组排序

int num[100];

int cmp ( const void *a , const void *b )
{
      return *(int *)a - *(int *)b;
}

 

 

////qsort对int类型的数组排序

#include<iostream>

using namespace std;

 

int num[100];

int cmp(const void* a,const void* b)

{

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

}

int main()

{

    intn,i;

    cout<<"请输入数组大小:"<<endl;

    cin>>n;

    for(i=0;i<n;i++)///初始化

       cin>>num[i];

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

    for(i=0;i<n;i++)

    {

       if(i==n-1)

           cout<<num[i]<<endl;

       else

           cout<<num[i]<<" ";

    }

    return0;

}

二、对char类型数组排序(同int类型)

char word[100];

int cmp( const void *a , const void *b )
{
      return *(char *)a - *(char *)b;
}

qsort(word,100,sizeof(word[0]),cmp);

 

注:按ASCII码排序,类似int

////qsort对char类型的数组排序

#include<iostream>

using namespace std;

 

char num[100];

int cmp(const void* a,const void* b)

{

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

}

int main()

{

    intn,i;

    cout<<"请输入数组大小:"<<endl;

    cin>>n;

    for(i=0;i<n;i++)///初始化

       cin>>num[i];

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

    for(i=0;i<n;i++)

    {

       if(i==n-1)

           cout<<num[i]<<endl;

       else

           cout<<num[i]<<" ";

    }

    return0;}

三、对double类型数组排序

double in[100];

int cmp( const void *a , const void *b )
{
      return *(double *)a > *(double*)b ? 1 : -1;
}

qsort(in,100,sizeof(in[0]),cmp);

 

 

 

////qsort对double类型的数组排序

#include<iostream>

using namespace std;

 

double num[100];

int cmp(const void* a,const void* b)

{

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

}

int main()

{

    intn,i;

    cout<<"请输入数组大小:"<<endl;

    cin>>n;

    for(i=0;i<n;i++)///初始化

       cin>>num[i];

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

    for(i=0;i<n;i++)

    {

       if(i==n-1)

           cout<<num[i]<<endl;

       else

           cout<<num[i]<<" ";

    }

       return 0;}

 

 

 

四、对结构体一级排序
struct Sample

{

    doubledata;

    intother;

}s[100];

 

//按照data的值从小到大将结构体排序

int cmp( const void *a ,const void *b)

{

    return(*(Sample *)a).data > (*(Sample *)b).data ? 1 : -1;

}

 

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

 

////程序

////qsort对结构类型的数组一级排序

#include<iostream>

using namespace std;

 

struct Sample

{

    intdata;

    charother;

};

 

Sample num[100];///结构数组

 

int cmp(const void* a,const void* b)

{

    return((Sample*)a)->data - ((Sample*)b)->data;

    //return(*(Sample*)a).data - (*(Sample*)b).data;也行的,一个是解引用,一个是直接指针指向

}

int main()

{

    intn,i;

    cout<<"请输入数组大小:"<<endl;

    cin>>n;

    for(i=0;i<n;i++)///初始化

       cin>>num[i].data>>num[i].other;

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

    for(i=0;i<n;i++)

    {

       if(i==n-1)

           cout<<num[i].data<<" "<<num[i].other<<endl;

       else

           cout<<num[i].data<<" "<<num[i].other<<" ";

    }

    return0;

}

五、对结构体二级排序
 

struct Sample

{

int x;

int y;

}s[100];

 

//按照x从小到大排序,当x相等时按照y从大到小排序

 

int cmp( const void *a , const void *b )

{

    structSample *c = (Sample *)a;

    structSample *d = (Sample *)b;

    if(c->x!= d->x)

       returnc->x - d->x;

    else

       return d->y - c->y;

}

 

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

 

 

 

////qsort对结构类型的数组二级排序

#include<iostream>

using namespace std;

 

struct Sample

{

    intdata;

    charother;

};

Sample num[100];///结构数组

int cmp(const void* a,const void* b)

{

    Sample *c = (Sample*)a;

    Sample *d = (Sample*)b;

    if(c->data== d->data)

       returnc->other - d->other;////如果结构体中的data相等则执行第二级排序

    else

       returnc->data - d->data;

}

int main()

{

    intn,i;

    cout<<"请输入数组大小:"<<endl;

    cin>>n;

    for(i=0;i<n;i++)///初始化

       cin>>num[i].data>>num[i].other;

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

    for(i=0;i<n;i++)

    {

       if(i==n-1)

           cout<<num[i].data<<" "<<num[i].other<<endl;

       else

           cout<<num[i].data<<" "<<num[i].other<<" ";

    }

    return0;

}

六、对字符串进行排序

struct Sample

{

    intdata;

    charstr[100];

}s[100];

 

//按照结构体中字符串str的字典顺序排序

int cmp ( const void *a , const void *b )

{

    returnstrcmp( (*(Sample *)a)->str , (*(Sample *)b)->str );

}

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

////对字符串进行排序

#include<iostream>

using namespace std;

struct Sample

{

    charch[100];

};

Sample num[100];///结构数组

int cmp(const void* a,const void* b)

{

    returnstrcmp( ((Sample*)a)->ch,((Sample*)b)->ch );

}

int main()

{

    intn,i;

    cout<<"请输入数组大小:"<<endl;

    cin>>n;

    for(i=0;i<n;i++)///初始化

       cin>>num[i].ch;

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

    for(i=0;i<n;i++)

    {

       if(i==n-1)

           cout<<num[i].ch<<endl;

       else

           cout<<num[i].ch<<" ";

    }

    return0;

}

附加一个完整点的代码,对字符串二维数组排序:

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

 

char s[2001][1001];

 

int cmp(const void *a, const void *b){

    returnstrcmp((char *)a,(char*)b);

}

 

int main(){

    inti,n;

    scanf("%d",&n);

    getchar();

    for(i=0;i<n;i++)

           gets(s[i]);

    qsort(s,n,1001*sizeof(char),cmp);

    for(i=0;i<n;i++)

           puts(s[i]);

    return0;

}

Sort()函数类似,不再一步一步举例,可以自学了
2、sort()
sort 对给定区间所有元素进行排序

stable_sort 对给定区间所有元素进行稳定排序

partial_sort 对给定区间所有元素部分排序

partial_sort_copy 对给定区间复制并排序

nth_element 找出给定区间的某个位置对应的元素

is_sorted 判断一个区间是否已经排好序

partition 使得符合某个条件的元素放在前面

stable_partition 相对稳定的使得符合某个条件的元素放在前面

语法描述为:

(1)sort(begin,end),表示一个范围,例如:

i

nt _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按升序排序,说到这里可能就有人会问怎么样用它降序排列呢?这就是下一个讨论的内容。

(2)sort(begin,end,compare)

一种是自己编写一个比较函数来实现,接着调用三个参数的sort:sort(begin,end,compare)就成了。对于list容器,这个方法也适用,把compare作为sort的参数就可以了,即:sort(compare)。

1)自己编写compare函数:

bool compare(int a,int b)

{

 return a<b; //升序排列,如果改为return a>b,则为降序

}

int _tmain(int argc, _TCHAR* argv[])

{

  inta[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);

 for(i=0;i<20;i++)

 cout<<a[i]<<endl;

 return 0;

}

2)更进一步,让这种操作更加能适应变化。也就是说,能给比较函数一个参数,用来指示是按升序还是按降序排,这回轮到函数对象出场了。

为了描述方便,我先定义一个枚举类型EnumComp用来表示升序和降序。很简单:

enum Enumcomp{ASC,DESC};

然后开始用一个类来描述这个函数对象。它会根据它的参数来决定是采用“<”还是“>”。

class compare

{

 private:

 Enumcomp comp;

 public:

 compare(Enumcomp c):comp(c) {};

 bool operator () (int num1,int num2)

  {

 switch(comp)

  {

 case ASC:

 return num1<num2;

  case DESC:

  return num1>num2;

  }

  }

};

接下来使用 sort(begin,end,compare(ASC))实现升序,sort(begin,end,compare(DESC))实现降序。

主函数为:

int main()

{

  inta[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;

}

3)其实对于这么简单的任务(类型支持“<”、“>”等比较运算符),完全没必要自己写一个类出来。标准库里已经有现成的了,就在functional里,include进来就行了。functional提供了一堆基于模板的比较函数对象。它们是(看名字就知道意思了):equal_to、not_equal_to、greater、greater_equal、less、less_equal。对于这个问题来说,greater和less就足够了,直接拿过来用:

升序:sort(begin,end,less());

降序:sort(begin,end,greater()).

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;

}

4)既然有迭代器,如果是string 就可以使用反向迭代器来完成逆序排列,程序如下:

int main()

{

 string str("cvicses");

 string s(str.rbegin(),str.rend());

 cout << s <<endl;

 return 0;

}

猜你喜欢

转载自blog.csdn.net/weixin_43821944/article/details/86257331
今日推荐