前言:qsort和sort都是系统提供给我们的可以直接排序的两个函数。在面试的时候手写代码需要排序的时候可以直接去调用这两个函数 。我自己在A题目的时候遇到了排序函数的问题,用了sort , AC不过,用了qsort竟然过了。。搞不懂。来看一下两者的区别,并分析下当时出现的错误原因。
qsort:
- base 指向要排序数组的第一个对象,被转换为一个void*指针.
- num 无符号整形变量,从base指针指向的对象开始有多少个对象需要排序。
- size 无符号整形变量,代表数组中每个元素的大小
- compar 指向一个比较两个元素大小的函数。这个函数将会被qsort函数重复的调用来比较两个元素的大小,它的定义方式是固定的。
// // main.cpp // sortAndqsortExample // // Created by mini on 12/20/13. // Copyright (c) 2013 mini. All rights reserved. // #include <iostream> #include <string.h> using namespace std; int cmp (const void * a, const void * b) { if ( *(int*)a < *(int*)b ) return 1; else return -1; } int main(int argc, const char * argv[]) { int a[ ] = {5, 211111111, -211111111, 7, 8, 2}; qsort(a, 6, sizeof( a[ 0 ] ), cmp); for( int i = 0; i < 6; i++ ) cout << a[ i ] << " "; cout << endl; return 0; }
Output: 211111111 8 7 5 2 -211111111
int cmp (const void * a, const void * b) { return *( int * ) a - *( int * )b; }
如果直接写成这个样子的话,当排序的数组值很大的时候,有可能会造成溢出的问题。看下面的代码:
#include <iostream> #include <string.h> using namespace std; int cmp (const void * a, const void * b) { return *( int * ) a - *( int * )b; } int main(int argc, const char * argv[]) { int a[ ] = {5, 2147483646, -2147483646, 7, 8, 2}; qsort(a, 6, sizeof( a[ 0 ] ), cmp); for( int i = 0; i < 6; i++ ) cout << a[ i ] << " "; cout << endl; return 0; }
#include <iostream> #include <string.h> using namespace std; struct Student{ int number; int age; char s; }; int cmp (const void * a, const void * b) { struct Student * p = (Student *) a; struct Student * q = (Student *) b; if( p -> number < q -> number ) return -1; else if ( p ->number > q -> number ) return 1; else return ( p -> age < q -> age ) ? -1 : 1; } int main(int argc, const char * argv[]) { Student A[ 5 ]; A[ 0 ] = { 5,8,'c'}; A[ 1 ] = { 8,8,'c'}; A[ 2 ] = { 6,6,'c'}; A[ 3 ] = { 6,8,'c'}; A[ 4 ] = { 2,8,'c'}; qsort( A, 5, sizeof(Student), cmp ); for( int i = 0; i < 5; i++ ) cout << A[ i ].number << " " << A[ i ].age << " " << A[ i ].s << endl; return 0; }
output:
2 8 c 5 8 c 6 6 c 6 8 c 8 8 c
先按照number排序,如果number相等,按照age 从小到大排序.
Sort
1. 所有STL sort算法函数的名字列表:
sort 对给定区间所有元素进行排序
stable_sort 对给定区间所有元素进行稳定排序
partial_sort 对给定区间所有元素部分排序
partial_sort_copy 对给定区间复制并排序
nth_element 找出给定区间的某个位置对应的元素
is_sorted 判断一个区间是否已经排好序
partition 使得符合某个条件的元素放在前面
stable_partition 相对稳定的使得符合某个条件的元素放在前面
2.sort 函数
template< class RandomIt > void sort( RandomIt first, RandomIt last ); (1) template< class RandomIt, class Compare > void sort( RandomIt first, RandomIt last, Compare comp );
bool cmp(const Type1 &a, const Type2 &b);
参数的形式不一定要定义为const &,但是在cmp函数中不能修改参数的值。 函数返回true 如果第一参数小于第二个参数。
#include <algorithm> #include <iostream> #include <string> #include <array> using namespace std; bool cmp( const int & a, const int & b ){ return a < b; } int main() { array< int, 10 > s ={ 5,2,3,8,1,9,0,7,4,6}; sort( s.begin(), s.end(), less< int >()); //sort( s.begin(), s.end() ); for( int a: s ) cout << a << " "; cout << endl; sort( s.begin(), s.end(), greater< int >()); for( int a: s ) cout << a << " "; cout << endl; sort( s.begin(), s.end(), cmp); for( int a: s ) cout << a << " "; cout << endl; return 0; }
输出:
0 1 2 3 4 5 6 7 8 9 9 8 7 6 5 4 3 2 1 0 0 1 2 3 4 5 6 7 8 9
partial_sort:
template< class RandomIt > void partial_sort( RandomIt first, RandomIt middle, RandomIt last ); (1) template< class RandomIt, class Compare > void partial_sort( RandomIt first, RandomIt middle, RandomIt last, Compare comp ); (2)
这个函数的作用是[first,middle)区间中包含排序后的函数,这个排序函数也是不稳定函数,不能保证相同值的元素在排序后的前后次序不发生变化。 自定义函数和sort 类似。
#include <algorithm> #include <iostream> #include <string> #include <array> using namespace std; bool cmp( const int & a, const int & b ){ return a < b; } int main() { array< int, 10 > s ={ 5,2,3,8,1,9,0,7,4,6}; partial_sort( s.begin(), s.begin() + 4, s.end()); for( int a: s ) cout << a << " " ; cout << endl; return 0; }
output: 0 1 2 3 8 9 5 7 4 6 ,我们看到了 前 4个是排序好的,后面的是未排序的,次序和原先也不同,其实根据名字也可以看出来这个函数的作用。部分排序。。
3.stable_sort 稳定排序
#include <algorithm> #include <iostream> #include <string> #include <vector> using namespace std; struct Employee { Employee(int age, std::string name) : age(age), name(name) { } int age; string name; // Does not particpate in comparisons }; bool operator<(const Employee &lhs, const Employee &rhs) { return lhs.age < rhs.age; } int main() { std::vector<Employee> v = { Employee(108, "Haha"), Employee(108, "Zaphod"), Employee(108, "Ford"), Employee(32, "Arthur"), }; stable_sort(v.begin(), v.end()); for (const Employee &e : v) { cout << e.age << ", " << e.name << '\n'; } }
Output:
32, Arthur 108, Haha 108, Zaphod 108, Ford
可以看出值等于108的三个元素的前后次序是没有变化的,所以它叫稳定排序。
nth_element
template< class RandomIt > void nth_element( RandomIt first, RandomIt nth, RandomIt last ); (1) template< class RandomIt, class Compare > void nth_element( RandomIt first, RandomIt nth, RandomIt last, Compare comp ); (2)
函数作用:找到排序后在第n个位置上的元素,也就是说在n位置前面的元素都比n这个位置的元素小或者等于,n位置后面的元素都会大于等于这个元素。
#include <iostream> #include <vector> #include <algorithm> #include <functional> using namespace std; int main() { std::vector<int> v{5, 6, 4, 3, 2, 7, 9, 1, 0, 8}; std::nth_element(v.begin(), v.begin() + v.size()/2, v.end()); std::cout << "The median is " << v[v.size()/2] << '\n'; for( int a : v ) cout << a << " "; cout << endl; std::nth_element(v.begin(), v.begin()+1, v.end(), std::greater<int>()); std::cout << "The second largest element is " << v[1] << '\n'; for( int a : v ) cout << a << " "; cout << endl; }
The median is 5 0 1 2 3 4 5 6 7 9 8 The second largest element is 8 9 8 7 6 5 4 3 2 1 0
可以看出来,5前面都是比它小的,后面的都是比它大的。但是并不一定是排序的。