关于 C++ 中的排序,排除自己手写排序算法的轮子侠以外,大多都是调用 std::sort
,不过除了这个以外还有一些其他的排序的法子,一一介绍。
1. std::sort
和 std::stable_sort
1.1 std::sort
最经典的排序的方法莫过于 std::sort
了,好用而且通用性强。
template <class RandomAccessIterator>
void sort (RandomAccessIterator first, RandomAccessIterator last);
template <class RandomAccessIterator, class Compare>
void sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp);
官方的描述如下:
Sorts the elements in the range [first,last) into ascending order.
The elements are compared usingoperator <
for the first version, and comp for the second.
Equivalent elements are not guaranteed to keep their original relative order (see stable_sort).
要点有几个
- 第一二个参数为
iter
,指针也行
可以这样:
vector<int> vec = {3, 3, 1, 9, 5};
sort(vec.begin(), vec.end());
int arr[6] = {3, 3, 1, 9, 5};
sort(arr, arr + 6);
- 待排序类型必须已经实现了
<
操作符,或者也可以自行指定比较器,有两种方式
//方法一,实现 operator <
struct Item1
{
//....
bool operator < (Item1 &item) const
{
//...
}
};
vector<Item1> arr;
//...
sort(arr.begin(), arr.end());
//方法二,额外实现一个 cmp
auto cmp = [](int a, int b) -> bool
{
//...
};
vector<int> arr;
sort(arr.begin(), arr.end(), cmp);
sort
是不稳定排序
如果想用稳定排序,用 stable_sort
。
1.2 std::stable_sort
std::sort
是不稳定排序,而 stable_sort
是稳定的排序,其他的用法都一样。
2. 涉及排序的其他一些算法
2.1 std::partial_sort
template <class RandomAccessIterator>
void partial_sort (RandomAccessIterator first, RandomAccessIterator middle, RandomAccessIterator last);
template <class RandomAccessIterator, class Compare>
void partial_sort (RandomAccessIterator first, RandomAccessIterator middle, RandomAccessIterator last, Compare comp);
重新排列范围内的元素 [first,last) ,使
middle
之前的元素是整个范围内最小的元素,并按升序排列,而其余的元素没有任何特定的顺序。
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
bool myfunction(int i, int j)
{
return (i < j);
}
int main()
{
int myints[] = {9, 6, 7, 2, 5, 3, 1, 4, 8};
vector<int> myvector(myints, myints + 9);
// using default comparison (operator <):
partial_sort(myvector.begin(), myvector.begin() + 5, myvector.end());
// using function as comp
partial_sort(myvector.begin(), myvector.begin() + 5, myvector.end(), myfunction);
// print out content:
cout << "myvector contains:";
for (auto it = myvector.begin(); it != myvector.end(); ++it)
cout << ' ' << *it;
cout << '\n';
return 0;
}
输入结果: myvector contains: 1 2 3 4 5 9 7 6 8
可以看到前 5 个元素有序,后面几个元素乱序(但也和原先的顺序不一样)。
2.2 std::partial_sort_copy
template <class InputIterator, class RandomAccessIterator>
RandomAccessIterator partial_sort_copy(
InputIterator first, InputIterator last,
RandomAccessIterator result_first, RandomAccessIterator result_last);
template <class InputIterator, class RandomAccessIterator, class Compare>
RandomAccessIterator partial_sort_copy(
InputIterator first, InputIterator last,
RandomAccessIterator result_first, RandomAccessIterator result_last,
Compare comp);
将
[first, last)
进行排序,将结果写入[result_first, result_last)
,不改变[first, last)
自身的内容
最终写入多少看result
的空间有多大
返回指向结果序列中最后一个元素后面的元素的迭代器
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
bool myfunction(int i, int j)
{
return (i < j);
}
int main()
{
int myints[] = {9, 8, 7, 6, 5, 4, 3, 2, 1};
vector<int> myvector(5);
// using default comparison (operator <):
partial_sort_copy(myints, myints + 9, myvector.begin(), myvector.end());
// using function as comp
partial_sort_copy(myints, myints + 9, myvector.begin(), myvector.end(), myfunction);
// print out content:
cout << "myvector contains:";
for (auto it = myvector.begin(); it != myvector.end(); ++it)
cout << ' ' << *it;
cout << '\n';
return 0;
}
myvector contains: 1 2 3 4 5
2.3 std::nth_element
template <typename RandomAccessIterator>
void nth_element (RandomAccessIterator first, RandomAccessIterator nth,RandomAccessIterator last);
template <typename RandomAccessIterator, typename Compare>
void nth_element(RandomAccessIterator first, RandomAccessIterator nth,
RandomAccessIterator last, Compare comp);
重新排列范围内的元素[first,last) ,使第 n 个位置
nth
的元素是在排序序列中位于该位置的元素,其他元素没有任何特定的顺序。除了第n个之前的元素没有一个大于它,后面的元素也没有一个小于它。
相当于把快排中的 Partition
操作。
2.4 std::is_sorted
template <class ForwardIterator>
bool is_sorted(ForwardIterator first, ForwardIterator last);
template <class ForwardIterator, class Compare>
bool is_sorted(ForwardIterator first, ForwardIterator last, Compare comp);
3. priority_queue
这玩意就是一个堆,所以只要把元素 insert
进去,然后用 top
方法可以不断访问有序的元素。
4. set
/multiset
STL 里的 set
和 multiset
使用红黑树实现的,所以如果把元素 insert
进去,然后遍历整个集合的话,会得到一个有序序列。