【C++】C++中的排序:不只是 std::sort

关于 C++ 中的排序,排除自己手写排序算法的轮子侠以外,大多都是调用 std::sort,不过除了这个以外还有一些其他的排序的法子,一一介绍。

1. std::sortstd::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 using operator < for the first version, and comp for the second.
Equivalent elements are not guaranteed to keep their original relative order (see stable_sort).

要点有几个

  1. 第一二个参数为 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);
  1. 待排序类型必须已经实现了 < 操作符,或者也可以自行指定比较器,有两种方式
//方法一,实现 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);
  1. 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 里的 setmultiset 使用红黑树实现的,所以如果把元素 insert 进去,然后遍历整个集合的话,会得到一个有序序列。

猜你喜欢

转载自blog.csdn.net/frostime/article/details/104980705