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
( #include < 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 ) 区间内的元素。只接受随机迭代器(5种迭代器中,继承层次最深)。
第一个函数原型,将默认使用 operator < 进行比较。所以对于此种类型,自定义的类必须提供 友元 operator < 运算符重载函数 或者 类成员operator < 函数 或者 全局的operator < 运算符重载函数 ,但是后面两种方式,要求涉及比较的成员变量非private属性。对于内置类型,默认使用less
仿函数(即按升序排列),若需要降序排列,指定比较器 greater
。
第二个函数原型,使用comp比较函数(二元谓词函数,以两个元素为参数,返回一个可转换成bool类型的值),可以是仿函数、函数指针 和 lambda表达式。comp只有返回 false 时,才会导致两个参数交换位置。
遵循严格弱序 —— strict weak order ( 让比较函数对相等的值返回 false )
两个元素相等的情况下,并不保证保持他们的原有顺序。如果想保持原有顺序,请使用 stable_sort()。
#include
#include
#include
#include
#define CLASSFOO_VECTOR(type, name, ...) \
static const type name##_a[] = __VA_ARGS__; \
std::vector name(name##_a, name##_a + sizeof(name##_a) / sizeof(*name##_a))
namespace ClassFoo{
bool IsGreater(int m, int n) { // 自定义的比较器comp , 普通函数
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;
}
#include
#include //sort
#include
#include //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 < (const Node&a,const Node&b)
{
//对于自定义的类,如果采用第一种原型,必须定义一个友元仿函数(operator <)。
//友元函数:是指某些虽然不是类的成员,却能够访问类的所有成员的函数。友元函数本身不属于类,但是可以访问类的私有成员。
// cout << "<" <
if (a.x == b.x)
return a.y < b.y;
return a.x < b.x;
}
friend bool operator > (const Node&a,const Node&b)
{
cout << ">" <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 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(std::cout," "));
std::cout << std::endl;
}
}
int main()
{
ClassFoo::Sort_2();
return 0;
}
#include
#include
#include
#include
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 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 ::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 // std::cout
#include // std::partial_sort
#include // std::vector
bool myfunction (int i,int j) { return (iint 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 // std::cout
#include // std::partial_sort_copy
#include // std::vector
bool myfunction (int i,int j) { return (iint 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
#include
#include
#include
#define CLASSFOO_VECTOR(type, name, ...) \
static const type name##_a[] = __VA_ARGS__; \
std::vector 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 // std::cout
#include // std::is_sorted_until, std::prev_permutation
#include // 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
#include
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;
}