q s o rt 基本快速排序的方法每次把数组分成两部分和中间的一个划分值而对于有多个重复值的数组来说基本快速排序的效率较低且不稳定 。集成在C语言库函数里面的的q so rt函数使用三路划分的方法解决排序这个问题。所谓三路划分是指把数组划分成小于划分值等于划分值和大于划分值的三个部分。
具体介绍 -^^void qsort(void*base, size_tnum, size_twidth, int (__cdecl *compare)int compare(constvoid*elem1,constvoid*elem2) );qsort 即 quicksort主要根据你给的比较条件给一个快速排序主要是通过指针移动实现排序功能。排序之后的结果仍然放在原来数组中。
参数意义如下:
第一个参数base是需要排序的目标数组名或者也可以理解成开始排序的地址 因为可以写&s[i]这样的表达式
第二个参数num是参与排序的目标数组元素个数
第三个参数width是单个元素的大小或者目标数组中每一个元素长度 推荐使用sizeof(s[0]这样的表达式
第四个参数compare就是让很多人觉得非常困惑的比较函数啦。
我们来简单讨论compare这个比较函数写成compare是我的个人喜好你可以随便写成什么比如cmp什么的在后面我会一直用cmp做解释 。
典型的compare的定义是int compare(constvoid*a,constvoid*b);
返回值必须是int两个参数的类型必须都是constvoid*那个a,b是随便写的个人喜好。假设是对int排序的话如果是升序那么就是如果a比b大返回一个正值小则负值相等返回0其他的依次类推后面有例子来说明对不同的类型如何进行排序。
q s o rt的使用方法
一、对i nt类型数组排序intnum[100];int cmp(constvoid*a,constvoid*b)
{return*(int*)a- *(int*)b; //升序排序
//return*(int*)b-*(int*)a;//降序排序
/*可见参数列表是两个空指针现在他要去指向你的数组元素。所以转型为你当前的类型然后取值。
升序排列时若第一个参数指针指向的“值”大于第二个参数指针指向的“值”则返回正若第一个参数指针指向的“值”等于第二个参数指针指向的“值”则返回零若第一个参数指针指向的“值”小于第二个参数指针指向的“值”则返回负。
降序排列时则刚好相反。
*/
}qsort(s,n,sizeof(s[0]),cmp);
示例完整函数已在VC6.0上运行通过
#include
#include
#includeints[10000],n,i;intcmp(constvoid*a,constvoid*b)
{return(*(int*)b-*(int*)a); //实现的是升序排序
}
intmain()
{
//输入想要输入的数的个数scanf("%d",&n);for(i=0;i
}
二、对char类型数组排序同int类型charword[100];intcmp(constvoid*a,constvoid*b)
{
//注意 网上很多版本是“return*(char*)a-*(int*)b; ”
//因为编辑者的不用心盲目copy 以讹传讹传的一直是错的*(int*)b//应该是return*(char*)a-*(char*)b;return*(char*)a-*(char*)b;
}qsort(word,100,sizeof(word[0]),cmp);
//附可能getchar();会派上用场
三、对double类型数组排序特别要注意
double in[100];intcmp(constvoid*a,constvoid*b)
{re t u rn*(d o u b le*)a>*(d o u b le*)b?1: -1;
//返回值的问题显然cmp返回的是一个整型所以避免double返回小数而被丢失用一个判断返回值。
}qsort(in,100,sizeof(in[0]),cmp);
//附排序结果的输出一般建议用“%g”格式
/*在这里多嘴一句 "%g"格式输出虽然书上是说系统会自动选择"%f"格式和"%e"格式中长度较短的格式并去掉无意义的0但实际上系统如果选择了"%e"系统会输出比“%e"格式更省一位的格式输出。 此结论来自VC6.0的实际操作 */
四、对结构体一级排序struct In
{doubledata;intother;
}s[100]
//按照data的值从小到大将结构体排序,关于结构体内的排序关键数据data的类型可以很多种参考上面的例子写intcmp(constvoid*a,constvoid*b)
{return(*(In*)a).data>(*(In*)b).data?1: -1;
//注意这条语句在VC6.0环境下运行可能会出错但是并不是语句错了而是你要先Bui ld或者全部重建。总之语句是对的。
//或者你可以将这上面1条语句改成下面这3条语句
//struct In*aa=(In*)a;
//struct In*bb=(In*)b;
//return aa->data>bb->data?1: -1;
}qsort(s,100,sizeof(s[0]),cmp);
五、对结构体二级排序struct In
{intx; //你可以比喻成失败次数inty; //你可以比喻成成功次数
}s[100];
//按照x从小到大排序当x相等时按照y从大到小排序。你可以想象成失败是主要因素的一个问题先比较失败次数少失败次数相同再看成功次数多。intcmp(constvoid*a,constvoid*b)
{struct In*c=(In*)a;struct In*d=(In*)b;if(c->x!=d->x) return c->x-d->x;elsereturnd->y-c->y;
}
qsort(s,100,sizeof(s[0]),cmp);
六、对字符串进行排序struct In
{intdata;charstr[100];
}s[100];
//按照结构体中字符串str的字典顺序排序int cmp(constvoid*a,constvoid*b)
{return strcmp( (*(In*)a)->str, (*(In*)b)->str);
}qsort(s,100,sizeof(s[0]),cmp);
注意 qsort中的cmp得自己写。
再说说s o rt 常用于C++sort使用时得注明 usingnamespace std;或直接打std: :sort()还得加上#include头文件
例
#include
#includeusingnamespacestd;
intmain()
{inta[20];for(int i=0;i<20;++i)cin>>a[i];s o rt(a,a+20); //范围很明显这里是a+20注意这是必要的如果是a+19for(i=0;i<20;i++) //最后一个值a[19]就不会参与排序。cout<
}std: :sort是一个改进版的qsort. std: :sort函数优于qsort的一些特点对大数组采取9项取样更完全的三路划分算法更细致的对不同数组大小采用不同方法排序。
最后我们来说说s o rt、 q s o rt的区别s o rt是q s o rt的升级版如果能用s o rt尽量用s o rt使用也比较简单不像q s ort还得自己去写cm p函数只要注明使用的库函数就可以使用参数只有两个如果是普通用法头指针和尾指针默认sort排序后是升序如果想让他降序排列可以使用自己编的cmp函数
#include
#include
usingnamespacestd;intcmp(inta,intb)
{if(ab则为降序,要注意sort()中cmp()的返值只有1和0不像qsort中存在1 e l sereturn 0;
}intmain(){int i;inta[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<