在学习数据结构的时候,我们会学习到很多不同的排序算法,比如说冒泡排序法,哈希表(大雾),以及快速排序。而C的函数库也给我们了一个快速排序的函数。就是我所提到的这个qsort。这个函数内部是一个写好了的快速排序算法的函数。头文件是#include<stdlib.h>。
我们首先需要来了解一下什么是快速排序,快速排序可以说是一种基于冒泡排序的衍生算法,它是对于冒泡排序的一种改进。快速排序法是最有效的排序算法之一,对大型数组而言更是如此。它的基本思想是,通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可以对这两部分记录继续进行排序,不断缩小数据结构,不断重复这个过程,以达到整个序列有序。这个算法我们会在我的另一个新篇(新坑)的数据结构中进行说明。我们今天要说明的是qsort()快速排序的这个算法。在ANSI原形中
void qsort(void *base,size_t nmemb,size_t size,int (*compar)(const void *,const void *));
猛一看,这个原形还是让人耳目一新啊(大雾)。分析一下这个函数所需要的参数:第一个参数为指向要排序的数组头部的指针。因为我们并不能够确定我们要排的序列的类型,是整形,浮点数,亦或是字符串。所以这里使用的是无符号指针,这样qsort函数的第一个十级参数可以指向任何类型的数组。第二个参数为需要排序的项目量,也就是我们要进行排序的数据的多少。函数原型将该值转换为size_t类型 ,并在标准头文件中定义该整数类型。(size_t类型是sizeof返回的类型的值。这是一个无符号整数类型,但它不是一个新的类型,相反与可移植类型相同,它是根据你标准类型定义的。它与typedef的使用有些相似,举个栗子,C的头文件系统可以使用typedef来使size_t在系统中作为unsigned int 啊 double之类的同义词。这样当我们使用size_t的时候,编译器就会使用适合我们系统的标准类型代替。)第三个参数则是我们需要传入我们需要警醒快速排序的参数的单独元素的大小,因为qsort()将第一个参数转换为void指针,所以会失去每个数组元素的大小信息,为补充这部分信息,必须把数据对象的大小明确地告诉qsort()。这就是第三个参数的作用。举个栗子,对int数组排序,就必须使用sizeof(int)作为第三个参数。
最后,qsort()还需要一个指向函数的指针,被指向的函数用于确定排序顺序,可以简单理解一下就是我们要怎么排序这个数组,是从小到大亦或是从大到小,都可以修改这里的参数进行实现。这个比较函数接受两个参数,就是分别指向进行比较的两个项目的指针。For example如果第一个项目的值大于第二个项目的值,那么比较函数返回正数;值相等返回值为0;相反则返回负数。qsort()根据给定的其他信息计算出两个指针值,然后把它们传递给该比较函数。这个参数实际上是一个函数。需要我们自己在使用的时候进行编写。我们单独把这个参数拿出来
int (*compar)(const void*,const coid*)
这表示最后的参数是个指向函数的指针,该函数返回Int值并接受两个参数,二每个参数均为指向const void类型的指针,const提醒我们这两个参数不能修改。这两个指针指向需要比较的项目。
整形排序的compar
int cmp ( const void *a , const void *b )
{
return *(int *)a - *(int *)b; //升序排序
//return *(int *)b - *(int *)a; //降序排序
字符串类型的compar
int cmp( const void *a , const void *b )
{
return *(char *)a - *(char *)b;
//return *(char *)a - *(char *)b;
}
double类型的compar
int cmp( const void *a , const void *b )
{
return *(double *)a > *(double *)b ? 1 : -1;
}
结构体类型的compar
int cmp( const void *a ,const void *b)
{ struct In *aa = (In *)a;
struct In *bb = (In *)b;
return aa->data > bb->data ? 1 : -1;
}
这些就是一些比较常用的compar参数的设置。
相对的在研究qsort的函数的同时,我也模仿着写了一个类似快速排序的冒泡排序
1
#include<stdio.h>
#include<windows.h>
#include<assert.h>
void bubble_char(void *data,int nums,int width,int(*comp)(void *,void*))
{
int i=0;
int k =0;
int j=0;
int flag =0;
assert(data);
for(;i<nums-1;i++)
{
char *start=(char*)data;
for(;j<nums-1;j++)
{
if(comp(start,start+width)>0)
for(;k<width;k++)
{
start[k]^=start[k+width];
start[k+width]^=start[k];
start[k]^=start[k+width];
}
flag=1;
}
start+=width;
if(!flag){
break;
}
}
}
int comp(void *x,void*y)
{
char*a=(char*)x;
char*b=(char*)y;
return *a-*b;
}
int main()
{
char arr[]="hello world ";
int len = sizeof(arr)/sizeof(arr[0]);
bubble_char(arr,len,sizeof(char),comp);
printf("%s",arr);
system("pause");
return 0;
}
这个便是使用了快速排序的冒泡排序来排序字符串类型的大小。也就是个字母排列。有兴趣的童鞋不妨试一试。如有问题 请各位大佬们指出。