排序——基于C++ STL的排序

12 篇文章 26 订阅
8 篇文章 0 订阅

概述

前面我们介绍了十种排序算法。在实际使用中,我们需要在每道 OI 题目中完成排序算法的具体实现。

C++提供了 STL(标准模板库),在这个模板库中,已经提供了排序相关函数。如下图所示。

下面我们介绍一下 STL 库的 sort()函数使用方法。

STL sort底层实现

STL中的sort不是普通的快排,除了对普通的快速排序进行优化,它还结合了插入排序堆排序。根据不同的数量级别以及不同情况,能自动选用合适的排序方法。当数据量较大时采用快速排序,分段递归。一旦分段后的数据量小于某个阀值,为避免递归调用带来过大的额外负荷,便会改用插入排序;而如果递归层次过深,有出现最坏情况的倾向,还会改用堆排序。

算法性能

时间复杂度

是比较排序中最好的时间复杂度。O(nlogn)

稳定性

不稳定

头文件

必须包括一个头文件

#include <algorithm>

sort函数原型

template <class RandomAccessIterator>
  void sort (RandomAccessIterator first, RandomAccessIterator last);
template <class RandomAccessIterator, class Compare>
  void sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp);

函数作用

从 [first, last) 范围内,对数列进行排序。

函数输入参数

first

进行排序的数量起点位置坐标。

second

进行排序的数量终点位置坐标。

注意:不包括这个位置。

comp

用户指定排序比较的方法。

是一个指向函数的指针。如果是缺省从小到大排序,这个函数指针可以不提供。函数的要求如下:

Binary function that accepts two elements in the range as arguments, and returns a value convertible to bool. The value returned indicates whether the element passed as first argument is considered to go before the second in the specific strict weak ordering it defines.
The function shall not modify any of its arguments.
This can either be a function pointer or a function object.

sort函数用法

从小到大排序

这个最简单。下面是一个简单的用例。

#include <iostream>     // std::cout
#include <algorithm>    // std::sort

int main () {
    int myints[] = {32,71,12,45,26,80,53,33};

    // using default comparison (operator <):
    std::sort(myints, myints+4); //对数组前面4个进行排序,排序后结果是(12 32 45 71) 26 80 53 33

    std::sort(myints+5, myints+8); // 12 32 45 71 26 (33 53 80)

    return 0;
}

从大到小排序

由于 STL 只提供缺省的从小到大排序,要进行从大到小排序,需要给定排序方法。也就是指定 comp 这个第三个参数。下面是一个简单的用例。

#include <iostream>     // std::cout
#include <algorithm>    // std::sort

bool mycmp(int x, int y) {
    //指定x和y的排序方法
    return x > y;
}

int main () {
    int myints[] = {32,71,12,45,26,80,53,33};

    std::sort(myints, myints+6, mycmp); //对数组前面6个进行从大到小排序,排序后结果是(80 71 45 32 26 12) 53 33

    std::sort(myints, myints+8, mycmp); //对数组前面6个进行从大到小排序,排序后结果是(80 71 53 45 33 32 26 11)


    return 0;
}

自定义数据类型排序

假设我们有一个如下所示结构体。

typedef struct {
    int age;//年龄
    char name[16];//名字
} MYST;

我们需要按照年级进行从小到大排序。程序实现如下。

#include <iostream>
#include <algorithm>

using namespace std;

typedef struct {
    int age;//年龄
    char name[16];//名字
} MYST;

const int MAXN = 1e6+2;
MYST data[MAXN] = {};//定义存储数据

//C++ 11标准
//自定义排序方法
bool mycmp(const MYST &x, const MYST &y) {
    //根据两个比较人的年级进行排序
    return x.age < y.age;
}

int main() {
    //读入数据
    int n;
    cin >> n;
    for (int i=0; i<n; i++) {
        cin >> data[i].age >> data[i].name;
    }

    //按照年龄进行排序
    sort(data, data+n, mycmp);

    //将排序结果输出
    for (int i=0; i<n; i++) {
        count << data[i].name << ' ' << data[i].age << endl;
    }
    cout << endl;
    
    return 0;
}

更复杂自定义排序

在上面例子排序上进一步升级,排序的条件如下:

1、年龄不同,按照年龄大小升序排序。

2、年龄相同,按照数据读入的顺序进行排序。

程序实现如下。

#include <iostream>
#include <algorithm>

using namespace std;

typedef struct {
    int age;//年龄
    int index;//数据索引
    char name[16];//名字
} MYST;

const int MAXN = 1e6+2;
MYST data[MAXN] = {};//定义存储数据

//C++ 11标准
//自定义排序方法
bool mycmp(const MYST &x, const MYST &y) {
    if (x.age != y.age) {
        //年龄不同,根据两个比较人的年级进行排序
        return x.age < y.age;    
    } else {
        //年龄相同,根据数据读入的顺序进行排序
        return x.index < y.index;
    }
}

int main() {
    //读入数据
    int n;
    cin >> n;
    for (int i=0; i<n; i++) {
        cin >> data[i].age >> data[i].name;
        data[i].index = i;
    }

    //按照年龄进行排序
    sort(data, data+n, mycmp);

    //将排序结果输出
    for (int i=0; i<n; i++) {
        count << data[i].name << ' ' << data[i].age << endl;
    }
    cout << endl;
    
    return 0;
}

总结

1、 STL sort()函数提供了极大的灵活性,为我们解决 OI 问题提供了极大便利。不仅仅是使用方便,而且时间复杂度也控制的很好。

2、灵活性体现在自定义的排序函数上。我们可以根据实际问题,实现自己的 comp 函数,已达到算法的灵活性。这也是 STL 的优点。

3、在使用上,我们先包含头文件 #include <algorithm>;然后自定义一个 comp 函数(这个可以没有,但是一般都需要自己写);直接调用 sort 函数,指定排序的起点位置指针和终点位置指针。

4、虽然 STL 的 sort 函数非常好用,但是基本的几种排序方法:冒泡排序、归并排序、快速排序都要能自己实现。因为将来有大量的面试知识和 OI 题需要使用到归并排序和快速排序的思想。

  • 1
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

努力的老周

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值