C++ 排序函数 sort(),qsort()的用法
2017-05-25 09:02
645 查看
C库函数qsort,C++库函数sort。其中qsort相对较慢,sort实现非常高效qsort:功 能: 使用快速排序例程进行排序头文件:#include<qsort>用 法: void qsort(void *base,int nelem,int width,int (*fcmp)(const void *,const void *));参数: 1 待排序数组首地址2 数组中待排序元素数量3 各元素的占用空间大小4 指向函数的指针,用于确定排序的顺序C++ qsort函数头文件:#include <algorithm>默认的sort函数是按升序排。所以自己总结了一下,首先看sort函数见下表:
要使用此函数只需用#include <algorithm> 即可使用sort,语法描述为:sort(begin,end),表示一个范围,例如: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(begin,end,compare)就成了。对于list容器,这个方法也适用,把compare作为sort的参数就可以了,即:sort(compare).
函数名 | 功能描述 |
---|---|
sort | 对给定区间所有元素进行排序 |
stable_sort | 对给定区间所有元素进行稳定排序 |
partial_sort | 对给定区间所有元素部分排序 |
partial_sort_copy | 对给定区间复制并排序 |
nth_element | 找出给定区间的某个位置对应的元素 |
is_sorted | 判断一个区间是否已经排好序 |
partition | 使得符合某个条件的元素放在前面 |
stable_partition | 相对稳定的使得符合某个条件的元素放在前面 |
sort(数组名,数组末地址,compare) //若不写compare则默认升序排列关于参数compare,compare带两个同类型的参数,如果第一个参数排在第二个参数前面4000,返回true,否则返回false1)自己编写compare函数:bool compare(int a,int b){ return a<b; //升序排列,如果改为return a>b,则为降序}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,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(){ 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;}3)其实对于这么简单的任务(类型支持“<”、“>”等比较运算符),完全没必要自己写一个类出来。标准库里已经有现成的了,就在functional里,include进来就行了。functional提供了一堆基于模板的比较函数对象。它们是(看名字就知道意思了):equal_to<Type>、not_equal_to<Type>、greater<Type>、greater_equal<Type>、less<Type>、less_equal<Type>。对于这个问题来说,greater和less就足够了,直接拿过来用:升序: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;}4)既然有迭代器,如果是string 就可以使用反向迭代器来完成逆序排列,程序如下:int main(){ string str("cvicses"); string s(str.rbegin(),str.rend()); cout << s <<endl; return 0;}STL容器的排序,支持随机访问的容器vector,deque,string没有sort成员,可调用std::sort排序;list排序调用自带的list::sort。下面是std::sort函数,有两个版本:[cpp] viewplaincopytemplate <class RandomAccessIterator> void sort ( RandomAccessIterator first, RandomAccessIterator last ); template <class RandomAccessIterator, class Compare> void sort ( RandomAccessIterator first, RandomAccessIterator last, Compare comp ); sort函数有以下特征:1. 要求输入一个范围[first, last)2. 随机迭代器,能用此算法的容器是支持随机访问的容器:vector, deque, string。3.第一个版本使用operator<进行比较,默认升序排序,第二个版本使用comp做比较.关于参数comp,comp带两个同类型的参数,如果第一个参数排在第二个参数前面,返回true,否则返回false它可以是函数指针,也可以是函数对象。函数指针好理解,何谓函数对象?函数对象(Function Object),是重载了operator()函数的类(或结构体)实例化出来的对象,使用起来像函数,又叫仿函数。STL本身提供了几个比较函数,下面这些都是仿函数:less(小于)greater(大于)equal_to(等于)not_equal_to(不相等)less_equal(小于等于)greater_equal(大于等于)当容器元素为内建类型时可以使用,注意使用的格式,要加模版参数(由于是模板类)和后面的(),如下:[cpp] viewplaincopysort(vec.begin(), vec.end(), less<int>()); 对于复合类型,实现排序方式有3种方法:1)重载operator<操作符2)写全局的比较函数3)写仿函数,重载operator()形式为:booloperator()(const 类名& 参数){…}下面看看这3种方法的实现:[cpp] viewplaincopy// 排序元素,比较的对象 struct Person { Person(int id, const string& name, int age): id_(id), name_(name), age_(age) {} int id_; string name_; int age_; }; [cpp] viewplaincopy// 方式1:重载operator<用于排序时的比较(写在函数体内) bool operator< (const Person& rt) { return this->id_ < rt.id_; } // 排序函数写法,默认调用operator< sort(members.begin(), members.end()); [cpp] viewplaincopy// 方式2:写比较函数 bool CompAge(const Person& pl, const Person& pr) { return pl.age_ < pr.age_; } // 排序时传入比较函数指针 sort(members.begin(), members.end(), CompAge); [cpp] viewplaincopy// 方式3:仿函数 struct CompName { bool operator()(const Person& pl, const Person& pr) { return pl.name_ < pr.name_; } }; // 排序时传入函数对象 sort(members.begin(), members.end(), CompName()); 用函数对象代替函数指针的优点:1. 函数对象可以存储中间结果在数据成员中,而函数想要存中间结果须要设全局变量或静态变量,这个是我们不想要的。2. 在函数对象中编译器可以实现内联调用,从而提升性能。下面看一个函数对象的扩展应用[cpp] viewplaincopy// 利用函数对象实现升降排序 struct CompNameEx{ CompNameEx(bool asce) : asce_(asce) {} bool operator()(const Person& pl, const Person& pr) { return asce_ ? pl.name_ < pr.name_ : pr.name_ < pl.name_;<span style="white-space:pre"> </span>// 《Eff STL》条款21: 永远让比较函数对相等的值返回false } private: bool asce_; }; // 使用仿函数排序(升降序) sort(members.begin(), members.end(), CompNameEx(false)); 注意:如果是指针的容器,比较函数的参数也应是指针。
C++sort()函数的用法
近来看了c++标准库这本书,学到了很多,就把这其中的一点C++sort()函数的用法写下来和大家分享吧!
(一)为什么要用c++标准库里的排序函数Sort()函数是c++一种排序方法之一,学会了这种方法也打消我学习c++以来使用的冒泡排序和选择排序所带来的执行效率不高的问题!因为它使用的排序方法是类似于快排的方法,时间复杂度为n*log2(n),执行效率较高!(二)c++标准库里的排序函数的使用方法I)Sort函数包含在头文件为#include<algorithm>的c++标准库中,调用标准库里的排序方法可以不必知道其内部是如何实现的,只要出现我们想要的结果即可!II)Sort函数有三个参数:(1)第一个是要排序的数组的起始地址。(2)第二个是结束的地址(最后一位要排序的地址)(3)第三个参数是排序的方法,可以是从大到小也可是从小到大,还可以不写第三个参数,此时默认的排序方法是从小到大排序。Sort函数使用模板:Sort(start,end,排序方法)下面就具体使用sort()函数结合对数组里的十个数进行排序做一个说明!例一:sort函数没有第三个参数,实现的是从小到大#include<iostream>#include<algorithm>using namespace std;int main(){ int a[10]={9,6,3,8,5,2,7,4,1,0}; for(int i=0;i<10;i++) cout<<a[i]<<endl;sort(a,a+10); for(int i=0;i<10;i++) cout<<a[i]<<endl; return 0;}例二通过上面的例子,会产生疑问:要实现从大到小的排序肿么办? 这就如前文所说需要在sort()函数里的第三个参数里做文章了,告诉程序我要从大到小排序!需要加入一个比较函数 complare(),此函数的实现过程是这样的bool complare(int a,int b){ return a>b;}这就是告诉程序要实现从大到小的排序的方法!#include<iostream>#include<algorithm>using namespace std;bool complare(int a,int b){ return a>b;}int main(){ int a[10]={9,6,3,8,5,2,7,4,1,0}; for(int i=0;i<10;i++) cout<<a[i]<<endl; sort(a,a+10,complare);//在这里就不需要对complare函数传入参数了,//这是规则 for(int i=0;i<10;i++) cout<<a[i]<<endl; return 0;}例三:通过上面例一、二的方法虽然实现了从大到小和从大到小的排序,这样做还是有点麻烦,因为还需要自己编写告诉程序执行何种排序的原则的函数,c++标准库强大的功能完全可以解决这种麻烦。Sortt函数的第三个参数可以用这样的语句告诉程序你所采用的排序原则less<数据类型>()//从小到大排序greater<数据类型>()//从大到小排序结合本例子,这样的就可以完成你想要的任何一种排序原则了#include<iostream>#include<algorithm>using namespace std;int main(){ int a[10]={9,6,3,8,5,2,7,4,1,0}; for(int i=0;i<10;i++) cout<<a[i]<<endl;sort(a,a+10,less<int>()); for(int i=0;i<10;i++) cout<<a[i]<<endl; return 0;}#include<iostream>#include<algorithm>using namespace std;int main(){ int a[10]={9,6,3,8,5,2,7,4,1,0}; for(int i=0;i<10;i++) cout<<a[i]<<endl; sort(a,a+10,greater<int>()); for(int i=0;i<10;i++) cout<<a[i]<<endl; return 0;}例四:利用sort函数还可以实现对字符的排序,排序方法大同小异,下面就把程序范例展示一下#include<iostream>#include<algorithm>using namespace std;int main(){ char a[11]="asdfghjklk"; for(int i=0;i<10;i++) cout<<a[i]<<endl; sort(a,a+10,greater<char>()); for(int i=0;i<10;i++) cout<<a[i]<<endl; return 0;} qsort():原型:_CRTIMP void __cdecl qsort (void*, size_t, size_t,int (*)(const void*, const void*));解释: qsort ( 数组名 ,元素个数,元素占用的空间(sizeof),比较函数) 比较函数是一个自己写的函数 遵循 int com(const void *a,const void *b) 的格式。当a b关系为 > < = 时,分别返回正值 负值 零 (或者相反)。使用a b 时要强制转换类型,从void * 转换回应有的类型后,进行操作。 数组下标从零开始,个数为N, 下标0-(n-1)。排序的顺序是从大到小还是从小到大取决于compare函数int compare(const void*a,const void*b){return *(*int)a-*(int*)b;} //升序排序的写法,
示例:qsort(a,10,sizeof(int),compare) //假设已定义了整型数组a[10] 如果是:return *(*int)b-*(int*)a 就是降序,不论是什么类型的数组,该函数的形式都是这样的
qsort 函数执行期间,需要比较两个元素哪个应在前面时,就以两个元素的地址作为参数,调用 Compare 函数。如果返回值小于0,则qsort 就得知第一个元素应该在前,如果返回值大于0,则第一个元素应该在后。如果返回值等于0,则哪个在前都行。qsort 函数的用法规定,“比较函数”的原型应是:int 函数名(const void * elem1, const void * elem2);该函数的两个参数,elem1 和elem2,指向待比较的两个元素。也就是说, * elem1 和* elem2 就是待比较的两个元素。该函数必须具有以下行为: 1) 如果 * elem1 应该排在 * elem2 前面,则函数返回值是负整数(任何负整数都行)。 2) 如果 * elem1 和* elem2 哪个排在前面都行,那么函数返回0 3) 如果 * elem1 应该排在 * elem2 后面,则函数返回值是正整数(任何正整数都行)。一定注意qsort与sort函数中自定义的比较函数compare中哪个元素应该排在前面的要求是不同的。实例:int compare(const void *a,const void *b){ return *(int*)b-*(int*)a; }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; qsort((void *)a,20,sizeof(int),compare); for(i=0;i<20;i++) cout<<a[i]<<endl; return 0;}相关:1)why你必须给予元素个数?因为阵列不知道它自己有多少个元素2)why你必须给予大小?因为 qsort 不知道它要排序的单位.3)why你必须写那个丑陋的、用来比较俩数值的函式?因为 qsort 需要一个指标指向某个函式,因为它不知道它所要排序的元素型别.4)why qsort 所使用的比较函式接受的是 const void* 引数而不是 char* 引数?因为 qsort 可以对非字串的数值排序. C/C++中有一个快速排序的标准库函数 qsort ,在stdlib.h 中声明,其原型为:void qsort(void *base, int nelem, unsigned int width, int ( * pfCompare)( const void *, const void *)); 使用该函数,可以对任何类型的一维数组排序。该函数参数中,base 是待排序数组的起始地址,nelem 是待排序数组的元素个数,width 是待排序数组的每个元素的大小(以字节为单位),最后一个参数 pfCompare 是一个函数指针,它指向一个“比较函数”。排序就是一个不断比较并交换位置的过程。qsort 如何在连元素的类型是什么都不知道的情况下,比较两个元素并判断哪个应该在前呢?答案是,qsort 函数在执行期间,会通过pfCompare指针调用一个 “比较函数”,用以判断两个元素哪个更应该排在前面。这个“比较函数”不是C/C++的库函数,而是由使用qsort的程序员编写的。在调用qsort 时, 将“比较函数”的名字作为实参传递给pfCompare。程序员当然清楚该按什么规则决定哪个元素应该在前,哪个元素应该在后,这个规则就体现在“比较函数”中。qsort 函数的用法规定,“比较函数”的原型应是:int 函数名(const void * elem1, const void * elem2);该函数的两个参数,elem1 和elem2,指向待比较的两个元素。也就是说, * elem1 和* elem2 就是待比较的两个元素。该函数必须具有以下行为: 1) 如果 * elem1 应该排在 * elem2 前面,则函数返回值是负整数(任何负整数都行)。 2) 如果 * elem1 和* elem2 哪个排在前面都行,那么函数返回0 3) 如果 * elem1 应该排在 * elem2 后面,则函数返回值是正整数(任何正整数都行)。例如:#include <iostream>#include <stdio.h>#include <stdlib.h>using namespace std;int compare(const void *a, const void *b){ int *pa = (int*)a; int *pb = (int*)b; return (*pa )- (*pb); //从小到大排序}void main(){ int a[10] = {5, 6, 4, 3, 7, 0 ,8, 9, 2, 1}; qsort(a, 10, sizeof(int), compare); for (int i = 0; i < 10; i++) cout << a[i] << " " << endl;} 再如:下面的程序,功能是调用qsort 库函数,将一个unsigned int 数组按照个位数从小到大进行排序。比如 8,23,15 三个数,按个位数从小到大排序,就应该是 23,15,8:#include <stdio.h>#include <stdlib.h>int MyCompare( const void * elem1, const void * elem2{ unsigned int * p1, * p2; p1 = (unsigned int *) elem1; //语句6 p2 = (unsigned int *) elem2; //语句7 return (* p1 % 10) - (* p2 % 10 ); //语句8}#define NUM 5int main(){ unsigned int an[NUM] = { 8,123,11,10,4 }; qsort( an, NUM, sizeof(unsigned int), MyCompare); for( int i = 0;i < NUM; i ++ ) printf("%d ", an[i]); return 0;} 上面程序的输出结果是:10 11 123 4 8qsort 函数执行期间,需要比较两个元素哪个应在前面时,就以两个元素的地址作为参数,调用 MyCompare 函数。如果返回值小于0,则qsort 就得知第一个元素应该在前,如果返回值大于0,则第一个元素应该在后。如果返回值等于0,则哪个在前都行。对语句6 解释如下:由于elem1 是 const void * 类型的,是void 指针,那么表达式“*elem1”是没有意义的。elem1 应指向待比较的元素,即一个unsigned int 类型的变量,所以要经过强制类型转换,将elem1 里存放的地址赋值给 p1,这样,* p1 就是待比较的第一个元素了。语句7 同理。语句8 体现了排序的规则。如果 *p1 的个位数小于 *p2 的个位数,那么就返回负值。其他两种情况不再赘述。
相关文章推荐
- C++ 排序函数 sort(),qsort()的用法【转】
- C++ 排序函数 sort(),qsort()的用法
- C++ 排序函数 sort(),qsort()的用法
- C++STL 排序函数sort和qsort的用法与区别
- C++ 排序函数 sort(),qsort()的用法
- C++ 排序函数 sort(),qsort()的用法
- C++ 排序函数 sort(),qsort()的用法
- C++ 排序函数 sort(),qsort()的用法
- C++ 排序函数 sort(),qsort()的用法
- C++ 排序函数 sort(),qsort()的用法
- C++ 排序函数 sort(),qsort()的用法
- C++ 排序函数 sort(),qsort()的用法
- C++ 排序函数 sort(),qsort()的用法
- C++ 排序函数 sort(),qsort()的用法
- C++ 排序函数 sort(),qsort()的用法
- C++ 排序函数 sort(),qsort()的用法
- C++ 排序函数 sort(),qsort()的用法 附加.str()用法
- C++ 排序函数 sort(),qsort()的用法
- C++ 排序函数 sort(),qsort()的用法
- C++ 排序函数 sort(),qsort()的用法(转载)