stl算法库中提供的排序相关算法主要有以下几种,除了q_sort定义在cstdlib头文件中,其余都定义在algorithm头文件。
算法 | 功能 |
---|---|
sort | 排序 |
stable_sort | 稳定排序:保证等值情况时的原有顺序 |
partial_sort | 部分排序:选择(mid-first)个最小值按升序排列 |
partial_sort_copy | 对排序结果,部分拷贝 |
nth_element | 按指定nth元素,划分左右 |
is_sorted | 检测指定范围是否按指定排序方式排序 |
is_sorted_until | 返回第一个未按指定排序方式排序的元素迭代器 |
q_sort | c语言库中提供的快速排序 |
以上排序算法默认按照升序排列,若需要降序排列,可以指定比较器comp为greater<type>()
(头文件functional) 。对于C/C++非内置类型,需要提供 仿函数、lambda表达式 或者 友元比较函数。
函数原型:
template <class RandomAccessIterator>
void sort (RandomAccessIterator first, RandomAccessIterator last);
template <class RandomAccessIterator, class Compare>
void sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp)
以升序排列[first,last)区间内的元素。
第一个函数原型,将默认使用operator <进行比较,所以对于此种类型,自定义的类必须提供 友元operator <运算符重载函数,因为默认情况下,内置类型才能够进行比较运算。对于内置类型,默认使用less<type>()
仿函数(即按升序排列)。
第二个函数原型,使用comp比较函数(二元谓词函数,以两个元素为参数,返回一个可转换成bool类型的值),可以是仿函数、函数指针 和 lambda表达式。comp只有返回false时,才会导致两个参数交换位置。
两个元素相等的情况下,并不保证保持他们的原有顺序。如果想保持原有顺序,请使用stable_sort()。
示例1:
内置类型的排序。
#include <iostream>
#include <algorithm>
#include <iterator>
#include <vector>
#define CLASSFOO_VECTOR(type, name, ...) \
static const type name##_a[] = __VA_ARGS__; \
std::vector<type> name(name##_a, name##_a + sizeof(name##_a) / sizeof(*name##_a))
namespace ClassFoo{
bool IsGreater(int m, int n) {
return m > n;
}
struct _IsLess{
bool operator()(int m, int n) {
return m < n;
}
}IsLess;
void Sort_1() {
CLASSFOO_VECTOR(int, BigVector1, { 8, 23, -5, 7, 29, 0, 7, 7, -7, 1, -1 });
// 使用 operator<
std::sort(
std::begin(BigVector1),
std::end(BigVector1)
);
// 输出结果
std::copy(
BigVector1.begin(),
BigVector1.end(),
std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
// 使用自定义函数
std::sort(
std::begin(BigVector1),
std::end(BigVector1),
IsGreater
);
// 输出结果
std::copy(
BigVector1.begin(),
BigVector1.end(),
std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
// 使用函数对象
std::sort(
std::begin(BigVector1),
std::end(BigVector1),
IsLess
);
// 输出结果
std::copy(
BigVector1.begin(),
BigVector1.end(),
std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
}
}
int main()
{
ClassFoo::Sort_1();
return 0;
}
示例2:
对象(自定义类)数组排序。
#include <iostream>
#include <algorithm> //sort
#include <vector>
#include <iterator> //ostream_iterator
using namespace std;
namespace ClassFoo{
class Node{
public:
Node(int m, int n) : x(m), y(n) {}
int x;
int y;
friend bool operator<(Node&a,Node&b)
{ //对于自定义的类,如果采用第一种原型,必须定义一个友元仿函数(operator <)。
//友元函数:是指某些虽然不是类的成员,却能够访问类的所有成员的函数。友元函数本身不属于类,但是可以访问类的私有成员。
cout << "<" <<endl;
if (a.x == b.x)
return a.y < b.y;
return a.x < b.x;
}
friend bool operator>(Node&a,Node&b)
{
cout << ">" <<endl;
if (a.x == b.x)
return a.y > b.y;
return a.x > b.x;
}
friend std::ostream& operator<<(std::ostream& o,const Node& a)
{
o << "(" << a.x << "," << a.y << ")";
return o;
}
};
//这种方式来重写输出函数也可以,但是只能访问Node的公有成员
/* ostream& operator << (ostream & out,const Node& a) { out << a.a; return out; }*/
// 此二元谓词函数 只能访问Node类的公有成员
bool MyNodeLessFunc(Node& a, Node& b) {
if (a.x == b.x)
return a.y < b.y;
return a.x < b.x;
}
void Sort_2() {
// 初始化对象数组
std::vector<Node> NodeVector;
NodeVector.push_back(Node(3, 7));
NodeVector.push_back(Node(1, 9));
NodeVector.push_back(Node(1, 3));
NodeVector.push_back(Node(6, 3));
NodeVector.push_back(Node(7, 2));
NodeVector.push_back(Node(6, 2));
// 排序
std::sort(
std::begin(NodeVector),
std::end(NodeVector)
//,MyNodeLessFunc
);
// 输出
copy(NodeVector.begin(),NodeVector.end(),std::ostream_iterator<Node>(std::cout," "));
std::cout << std::endl;
}
}
int main()
{
ClassFoo::Sort_2();
return 0;
}
示例3:
比较函数定义为lambda表达式。
#include <iostream>
#include <algorithm>
#include <iterator>
#include <vector>
namespace ClassFoo{
class Node{
public:
Node(int m, int n) : x(m), y(n) {}
int x;
int y;
};
std::ostream& operator<<(std::ostream& o, Node& a) {
o << "(" << a.x << "," << a.y << ")";
return o;
}
void Sort_3() {
// 初始化整数数组
std::vector<int> BigVector = { 8, 23, -5, 7, 29, 0, 7, 7, -7, 1, -1 };
// 初始化对象数组
std::vector<Node> NodeVector = { {3, 7}, {1, 9}, {1, 3}, {6, 3}, {7, 2}, {6, 2} };
// 排序整数数组
// 按从大到小排序
std::sort(
BigVector.begin(),
BigVector.end(),
[](int m, int n) { return m > n; }
);
// 输出结果
std::copy(
BigVector.begin(),
BigVector.end(),
std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
// 排序对象数组
std::sort(
std::begin(NodeVector),
std::end(NodeVector),
[](Node& a, Node& b) {
if (a.x == b.x)
return a.y < b.y;
return a.x < b.x;
}
);
// 输出
for (std::vector<Node>::iterator it = NodeVector.begin();
it != NodeVector.end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
}
}
int main()
{
ClassFoo::Sort_3();
return 0;
}
函数原型:
void stable_sort ( RandomAccessIterator first, RandomAccessIterator last );
void stable_sort ( RandomAccessIterator first, RandomAccessIterator last, Compare comp );
稳定排序:等值元素的先后关系保持不变,而 std::sort 不能保证该点。
其他基本使用方法,跟sort()一样。
示例可以参考上述代码。
函数原型:
void partial_sort (RandomAccessIterator first, RandomAccessIterator middle,
RandomAccessIterator last);
void partial_sort (RandomAccessIterator first, RandomAccessIterator middle,
RandomAccessIterator last, Compare comp);
部分排序:默认从[first,last)中选择(middle - first)个最小的元素,并按升序排列。其余元素不排序。
其余使用方法跟sort()类似。
示例4:
#include <iostream> // std::cout
#include <algorithm> // std::partial_sort
#include <vector> // std::vector
bool myfunction (int i,int j) { return (i<j); }
int main () {
int myints[] = {9,8,7,6,5,4,3,2,1};
std::vector<int> myvector (myints, myints+9);
// using default comparison (operator <):
std::partial_sort (myvector.begin(), myvector.begin()+5, myvector.end());
// using function as comp
std::partial_sort (myvector.begin(), myvector.begin()+5, myvector.end(),myfunction);
// print out content:
std::cout << "myvector contains:";
for (std::vector<int>::iterator it=myvector.begin(); it!=myvector.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
return 0;
}
函数原型:
inline _RandomAccessIterator
partial_sort_copy(_InputIterator __first, _InputIterator __last, _RandomAccessIterator __result_first, _RandomAccessIterator __result_last)
inline _RandomAccessIterator
partial_sort_copy(_InputIterator __first, _InputIterator __last, _RandomAccessIterator __result_first, _RandomAccessIterator __result_last, _Compare __comp)
示例5:
#include <iostream> // std::cout
#include <algorithm> // std::partial_sort_copy
#include <vector> // std::vector
bool myfunction (int i,int j) { return (i<j); }
int main () {
int myints[] = {9,8,7,6,5,4,3,2,1};
std::vector<int> myvector (5);
// using default comparison (operator <):
std::partial_sort_copy (myints, myints+9, myvector.begin(), myvector.end());
// using function as comp
std::partial_sort_copy (myints, myints+9, myvector.begin(), myvector.end(), myfunction);
// print out content:
std::cout << "myvector contains:";
for (std::vector<int>::iterator it=myvector.begin(); it!=myvector.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
return 0;
}
函数原型:
template <class RandomAccessIterator>
void nth_element (RandomAccessIterator first, RandomAccessIterator nth,
RandomAccessIterator last);
template <class RandomAccessIterator, class Compare>
void nth_element (RandomAccessIterator first, RandomAccessIterator nth,
RandomAccessIterator last, Compare comp);
示例6:
#include <iostream>
#include <algorithm>
#include <iterator>
#include <vector>
#define CLASSFOO_VECTOR(type, name, ...) \
static const type name##_a[] = __VA_ARGS__; \
std::vector<type> name(name##_a, name##_a + sizeof(name##_a) / sizeof(*name##_a))
namespace ClassFoo{
void NthElement_1() {
CLASSFOO_VECTOR(int, BigVector1, { 8, 23, -5, 7, 29, 0, 5, 7, -7, 1, -1 });
std::nth_element(
std::begin(BigVector1),
std::begin(BigVector1) + 6, // 按第 7 个元素(值为 5)划分
std::end(BigVector1)
);
// 输出结果
std::copy(
BigVector1.begin(),
BigVector1.end(),
std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
//参考结果:0 -1 -5 -7 5 1 7 7 8 29 23
}
}
int main()
{
ClassFoo::NthElement_1();
return 0;
}
函数原型:
template <class ForwardIterator>
bool is_sorted (ForwardIterator first, ForwardIterator last);
template <class ForwardIterator, class Compare>
bool is_sorted (ForwardIterator first, ForwardIterator last, Compare comp);
函数原型:
template <class ForwardIterator>
ForwardIterator is_sorted_until (
ForwardIterator first,
ForwardIterator last);
template <class ForwardIterator>
ForwardIterator is_sorted_until (
ForwardIterator first,
ForwardIterator last,
Compare comp);
示例7:
#include <iostream> // std::cout
#include <algorithm> // std::is_sorted_until, std::prev_permutation
#include <array> // std::array
int main () {
std::array<int,4> foo {2,4,1,3};
std::array<int,4>::iterator it;
do {
// try a new permutation:
std::prev_permutation(foo.begin(),foo.end());
// print range:
std::cout << "foo:";
for (int& x:foo)
std::cout << ' ' << x;
it=std::is_sorted_until(foo.begin(),foo.end());
std::cout << " (" << (it-foo.begin()) << " elements sorted)\n";
} while (it!=foo.end());
std::cout << "the range is sorted!\n";
return 0;
}
函数原型:
void qsort (void* base, size_t num, size_t size,
int (*compare)(const void* p1,const void* p2));
compare : 函数指针,其指向的函数用于比较两个元素。
示例8:
#include <iostream>
#include <cstdlib>
int MyIntCompare(const void* m, const void* n) {
return (*(int*)m - *(int*)n);
}
void QSort_1() {
int foo[] = { 8, 23, -5, 7, 29, 0, 7, 7, -7, 1, -1 };
int count = sizeof(foo) / sizeof(foo[0]);
std::qsort(
foo,
count,
sizeof(foo[0]),
MyIntCompare);
for (int i = 0; i < count; i++){
std::cout << foo[i] << " ";
}
std::cout << std::endl;
}
int main()
{
QSort_1();
return 0;
}